API reference
Every operation of the partner API 1.3.0, generated at build time from the contract the API serves.
Operation and field descriptions come from the contract, in English.
Court booking, court details, reviews and safety reports for partner apps. OAuth 2.0 client credentials. Webhooks (reservation.created, reservation.cancelled, reservation.no_show, reservation.completed, reservation.checked_in, review.replied, safety_report.resolved; ignore types you don't know) are signed with HMAC-SHA256: Ezaz-Signature: t=<unix>,v1=<hex of HMAC(secret, t + '.' + body)>; reject anything older than 5 minutes and dedupe on the event id. Errors are RFC 9457 problem details with a stable code.
Authentication
post/partner/oauth/token
Client credentials: a 10-minute access token for the partner API
Authenticate with HTTP Basic (client_secret_basic, preferred) or with client_id and client_secret in the form (client_secret_post). The token lasts 10 minutes (expires_in); ask for a new one when it ends, there is no refresh token. Answers are never cached. Who: any partner app Ezaz registered and hasn't suspended. Errors: 400 invalid_request, unsupported_grant_type or invalid_scope; 401 invalid_client: unknown client, wrong secret or suspended.
- Scope
- None: this is how you get a token
- operationId
partnerToken
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
Authorization | header | string | No | Basic base64(client_id:client_secret), for client_secret_basic |
Request body
Content type: application/x-www-form-urlencoded
| Name | Type | Required | Description |
|---|---|---|---|
client_id | string | No | Your client id (kp_…), with client_secret_post only |
client_secret | string | No | Your client secret (ks_…), with client_secret_post only |
grant_type | "client_credentials" | Yes | Always client_credentials |
scope | string | No | Scopes to ask for, separated by spaces; omit for all you were granted |
client_id=kp_your_client_id&client_secret=ks_your_client_secret&grant_type=client_credentials&scope=venues%3Aread%20availability%3AreadResponses
200 The token · application/json · PartnerToken
{
"access_token": "eyJhbGciOiJIUzI1NiJ9…",
"expires_in": 600,
"scope": "venues:read availability:read",
"token_type": "Bearer"
}Errors
| Status | Description | Content type |
|---|---|---|
400 | invalid_request, unsupported_grant_type or invalid_scope | application/jsonPartnerTokenError |
401 | invalid_client: unknown client, wrong secret or suspended | application/jsonPartnerTokenError |
Venues and courts
get/partner/v1/venues
List the venues that let you sell their courts
Active venues that granted you, with their address, area, contact phone, cancellation cutoff and active courts. Page with after (the previous page's nextCursor) until nextCursor is null; a page can be shorter than limit without being the last. Scopes: venues:read (the token needs every one). Errors: 400 VALIDATION_FAILED; 401 UNAUTHENTICATED; 403 FORBIDDEN; 429 PARTNER_RATE_LIMITED.
- Scope
venues:read- operationId
partnerListVenues
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
after | query | string (uuid) | No | The nextCursor of the previous page; omit for the first |
limit | query | integer (int32) | No | Page sizemin 1 · max 100 · default 50 |
Responses
200 OK · application/json · PartnerVenuePage
{
"items": [
{
"address": {
"ar": "string",
"en": "string"
},
"area": {
"code": "new-cairo",
"name": {
"ar": "string",
"en": "string"
}
},
"cancellationHours": 24,
"contactPhone": "+201001234567",
"courts": [
{
"courtId": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31",
"environment": "string",
"kind": "string",
"name": {
"ar": "string",
"en": "string"
}
}
],
"latitude": 30.0074,
"longitude": 31.4913,
"name": {
"ar": "string",
"en": "string"
},
"photoUrls": [
"string"
],
"venueId": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31"
}
],
"nextCursor": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31"
}Errors
Problem details (application/problem+json) with a stable code. Each code is explained under Errors, in Arabic and English.
| Status | Description | Content type |
|---|---|---|
400 | The request is invalid: VALIDATION_FAILED (with errors per field) | application/problem+jsonProblem |
401 | UNAUTHENTICATED: no token, an expired or invalid one, or a suspended partner | application/problem+jsonProblem |
403 | FORBIDDEN: the token lacks a scope this operation needs | application/problem+jsonProblem |
429 | PARTNER_RATE_LIMITED: over your per-minute budgetRetry-After (integer (int32)): Seconds until the budget resets | application/problem+jsonProblem |
get/partner/v1/venues/{venueId}/availability
Get free slots and prices on a Cairo date
Every active court's free slots of the given length (60, 90 or 120 minutes) starting on the half hour on that Cairo date, inside the venue's opening hours, with the list price of each. Slots are UTC instants; daylight saving is handled (a skipped hour has no slots). Scopes: availability:read (the token needs every one). Errors: 400 VALIDATION_FAILED; 401 UNAUTHENTICATED; 403 FORBIDDEN; 404 VENUE_NOT_FOUND; 429 PARTNER_RATE_LIMITED.
- Scope
availability:read- operationId
partnerAvailability
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
venueId | path | string (uuid) | Yes | The venue |
date | query | string (date) | Yes | A Cairo date (YYYY-MM-DD) |
minutes | query | integer (int32) | No | Session length: 60, 90 or 120default 60 |
Responses
200 OK · application/json · array of CourtSlots
[
{
"courtId": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31",
"slots": [
{
"end": "2026-10-10T17:00:00Z",
"price": {
"amount": 120000,
"currency": "EGP"
},
"start": "2026-10-10T17:00:00Z"
}
]
}
]Errors
Problem details (application/problem+json) with a stable code. Each code is explained under Errors, in Arabic and English.
| Status | Description | Content type |
|---|---|---|
400 | The request is invalid: VALIDATION_FAILED (with errors per field) | application/problem+jsonProblem |
401 | UNAUTHENTICATED: no token, an expired or invalid one, or a suspended partner | application/problem+jsonProblem |
403 | FORBIDDEN: the token lacks a scope this operation needs | application/problem+jsonProblem |
404 | Not found, or not yours to see (the same answer): VENUE_NOT_FOUND | application/problem+jsonProblem |
429 | PARTNER_RATE_LIMITED: over your per-minute budgetRetry-After (integer (int32)): Seconds until the budget resets | application/problem+jsonProblem |
get/partner/v1/venues/{venueId}/courts
List a venue's courts with their facts
The venue's active courts: facts (surface, walls, lighting, size, dates), public photos, the rating from published reviews (from 3 reviews) and the safety summary (open issues only, never the reports). Scopes: venues:read (the token needs every one). Errors: 401 UNAUTHENTICATED; 403 FORBIDDEN; 404 VENUE_NOT_FOUND; 429 PARTNER_RATE_LIMITED.
- Scope
venues:read- operationId
partnerListCourts
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
venueId | path | string (uuid) | Yes | The venue |
Responses
200 OK · application/json · array of CourtDetail
[
{
"courtId": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31",
"environment": "string",
"kind": "string",
"lastRenovatedOn": "2026-10-10",
"latestReviews": [
{
"authorName": "Omar H.",
"cleanliness": 1,
"comment": "Great glass and new turf.",
"courtId": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31",
"createdAt": "2026-10-10T17:00:00Z",
"id": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31",
"lighting": 1,
"overall": 1,
"repliedAt": "2026-10-10T17:00:00Z",
"reply": "Thanks, see you again!",
"surface": 1
}
],
"lighting": "string",
"name": {
"ar": "string",
"en": "string"
},
"openedOn": "2026-10-10",
"photoUrls": [
"string"
],
"rating": {
"average": 4.5,
"cleanliness": 1.5,
"count": 12,
"lighting": 1.5,
"surface": 1.5
},
"renovationNote": "string",
"safety": {
"lastResolvedOn": "2026-10-10",
"openIssues": 1
},
"size": "string",
"surface": "string",
"turfBrand": "string",
"venueId": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31",
"walls": "string"
}
]Errors
Problem details (application/problem+json) with a stable code. Each code is explained under Errors, in Arabic and English.
| Status | Description | Content type |
|---|---|---|
401 | UNAUTHENTICATED: no token, an expired or invalid one, or a suspended partner | application/problem+jsonProblem |
403 | FORBIDDEN: the token lacks a scope this operation needs | application/problem+jsonProblem |
404 | Not found, or not yours to see (the same answer): VENUE_NOT_FOUND | application/problem+jsonProblem |
429 | PARTNER_RATE_LIMITED: over your per-minute budgetRetry-After (integer (int32)): Seconds until the budget resets | application/problem+jsonProblem |
get/partner/v1/venues/{venueId}/courts/{courtId}
Get one court with its newest reviews
One active court as in the list, plus its newest published reviews. Scopes: venues:read (the token needs every one). Errors: 401 UNAUTHENTICATED; 403 FORBIDDEN; 404 VENUE_NOT_FOUND, COURT_NOT_FOUND; 429 PARTNER_RATE_LIMITED.
- Scope
venues:read- operationId
partnerGetCourt
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
venueId | path | string (uuid) | Yes | The venue |
courtId | path | string (uuid) | Yes | The court |
Responses
200 OK · application/json · CourtDetail
{
"courtId": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31",
"environment": "string",
"kind": "string",
"lastRenovatedOn": "2026-10-10",
"latestReviews": [
{
"authorName": "Omar H.",
"cleanliness": 1,
"comment": "Great glass and new turf.",
"courtId": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31",
"createdAt": "2026-10-10T17:00:00Z",
"id": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31",
"lighting": 1,
"overall": 1,
"repliedAt": "2026-10-10T17:00:00Z",
"reply": "Thanks, see you again!",
"surface": 1
}
],
"lighting": "string",
"name": {
"ar": "string",
"en": "string"
},
"openedOn": "2026-10-10",
"photoUrls": [
"string"
],
"rating": {
"average": 4.5,
"cleanliness": 1.5,
"count": 12,
"lighting": 1.5,
"surface": 1.5
},
"renovationNote": "string",
"safety": {
"lastResolvedOn": "2026-10-10",
"openIssues": 1
},
"size": "string",
"surface": "string",
"turfBrand": "string",
"venueId": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31",
"walls": "string"
}Errors
Problem details (application/problem+json) with a stable code. Each code is explained under Errors, in Arabic and English.
| Status | Description | Content type |
|---|---|---|
401 | UNAUTHENTICATED: no token, an expired or invalid one, or a suspended partner | application/problem+jsonProblem |
403 | FORBIDDEN: the token lacks a scope this operation needs | application/problem+jsonProblem |
404 | Not found, or not yours to see (the same answer): VENUE_NOT_FOUND, COURT_NOT_FOUND | application/problem+jsonProblem |
429 | PARTNER_RATE_LIMITED: over your per-minute budgetRetry-After (integer (int32)): Seconds until the budget resets | application/problem+jsonProblem |
get/partner/v1/venues/{venueId}/courts/{courtId}/reviews
List a court's published reviews
Published reviews of the court, newest first. Continue with before and beforeId set from the last item's createdAt and id. Hidden reviews never show. Scopes: venues:read (the token needs every one). Errors: 400 VALIDATION_FAILED; 401 UNAUTHENTICATED; 403 FORBIDDEN; 404 VENUE_NOT_FOUND, COURT_NOT_FOUND; 429 PARTNER_RATE_LIMITED.
- Scope
venues:read- operationId
partnerListCourtReviews
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
venueId | path | string (uuid) | Yes | The venue |
courtId | path | string (uuid) | Yes | The court |
before | query | string (date-time) | No | Continue after the item created at this instant (from the previous page) |
beforeId | query | string (uuid) | No | And with this id (ties) |
limit | query | integer (int32) | No | Page sizemin 1 · max 50 · default 20 |
Responses
200 OK · application/json · array of Review
[
{
"authorName": "Omar H.",
"cleanliness": 1,
"comment": "Great glass and new turf.",
"courtId": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31",
"createdAt": "2026-10-10T17:00:00Z",
"id": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31",
"lighting": 1,
"overall": 1,
"repliedAt": "2026-10-10T17:00:00Z",
"reply": "Thanks, see you again!",
"surface": 1
}
]Errors
Problem details (application/problem+json) with a stable code. Each code is explained under Errors, in Arabic and English.
| Status | Description | Content type |
|---|---|---|
400 | The request is invalid: VALIDATION_FAILED (with errors per field) | application/problem+jsonProblem |
401 | UNAUTHENTICATED: no token, an expired or invalid one, or a suspended partner | application/problem+jsonProblem |
403 | FORBIDDEN: the token lacks a scope this operation needs | application/problem+jsonProblem |
404 | Not found, or not yours to see (the same answer): VENUE_NOT_FOUND, COURT_NOT_FOUND | application/problem+jsonProblem |
429 | PARTNER_RATE_LIMITED: over your per-minute budgetRetry-After (integer (int32)): Seconds until the budget resets | application/problem+jsonProblem |
post/partner/v1/venues/{venueId}/player-passes
Get a player's packages and memberships at a venue
The packages (minutes left, expiry) and memberships (discount) the player holds at the venue, found by the phone you verified, sent in the body so it never lands in a URL or a log. Lookups are capped per partner app: 60 a minute and 3,000 a day. Scopes: passes:read (the token needs every one). Errors: 400 VALIDATION_FAILED, PHONE_INVALID; 401 UNAUTHENTICATED; 403 FORBIDDEN; 404 VENUE_NOT_FOUND; 429 PARTNER_RATE_LIMITED, PARTNER_PASS_LOOKUPS_LIMITED.
- Scope
passes:read- operationId
partnerPlayerPasses
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
venueId | path | string (uuid) | Yes | The venue |
Request body
Content type: application/json · PlayerLookupRequest
{
"phone": "+201001234567"
}Responses
200 OK · application/json · PlayerPasses
{
"memberships": [
{
"discountBps": 1000,
"endsAt": "2026-10-10T17:00:00Z",
"id": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31",
"name": {
"ar": "string",
"en": "string"
},
"startsAt": "2026-10-10T17:00:00Z"
}
],
"packages": [
{
"expiresAt": "2026-10-10T17:00:00Z",
"id": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31",
"minutesLeft": 1,
"minutesTotal": 1,
"name": {
"ar": "string",
"en": "string"
}
}
]
}Errors
Problem details (application/problem+json) with a stable code. Each code is explained under Errors, in Arabic and English.
| Status | Description | Content type |
|---|---|---|
400 | The request is invalid: VALIDATION_FAILED, PHONE_INVALID (with errors per field) | application/problem+jsonProblem |
401 | UNAUTHENTICATED: no token, an expired or invalid one, or a suspended partner | application/problem+jsonProblem |
403 | FORBIDDEN: the token lacks a scope this operation needs | application/problem+jsonProblem |
404 | Not found, or not yours to see (the same answer): VENUE_NOT_FOUND | application/problem+jsonProblem |
429 | PARTNER_RATE_LIMITED: over your per-minute budget; or PARTNER_PASS_LOOKUPS_LIMITED (60 a minute and 3,000 a day per partner app)Retry-After (integer (int32)): Seconds until the budget resets | application/problem+jsonProblem |
post/partner/v1/venues/{venueId}/quote
Quote a slot for your player
What the slot costs your player: the list price and, when their phone holds a membership at the venue, the member price, which is what they pay however it is paid, prepaid to you or at the venue (ADR 0015). Quote right before booking with PREPAID_BY_PARTNER so you collect the right amount. The phone goes in the body, never the URL. Scopes: availability:read, passes:read (the token needs every one). Errors: 400 VALIDATION_FAILED, PHONE_INVALID, COURT_SLOT_NOT_BOOKABLE; 401 UNAUTHENTICATED; 403 FORBIDDEN; 404 VENUE_NOT_FOUND, COURT_NOT_FOUND; 429 PARTNER_RATE_LIMITED.
- Scopes (the token needs all of them)
availability:readpasses:read- operationId
partnerQuote
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
venueId | path | string (uuid) | Yes | The venue |
Request body
Content type: application/json · QuoteRequest
{
"courtId": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31",
"minutes": 90,
"phone": "+201001234567",
"start": "2026-10-10T17:00:00Z"
}Responses
200 OK · application/json · Quote
{
"charge": {
"amount": 120000,
"currency": "EGP"
},
"courtId": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31",
"discountBps": 1000,
"end": "2026-10-10T17:00:00Z",
"price": {
"amount": 120000,
"currency": "EGP"
},
"start": "2026-10-10T17:00:00Z"
}Errors
Problem details (application/problem+json) with a stable code. Each code is explained under Errors, in Arabic and English.
| Status | Description | Content type |
|---|---|---|
400 | The request is invalid: VALIDATION_FAILED, PHONE_INVALID, COURT_SLOT_NOT_BOOKABLE (with errors per field) | application/problem+jsonProblem |
401 | UNAUTHENTICATED: no token, an expired or invalid one, or a suspended partner | application/problem+jsonProblem |
403 | FORBIDDEN: the token lacks a scope this operation needs | application/problem+jsonProblem |
404 | Not found, or not yours to see (the same answer): VENUE_NOT_FOUND, COURT_NOT_FOUND | application/problem+jsonProblem |
429 | PARTNER_RATE_LIMITED: over your per-minute budgetRetry-After (integer (int32)): Seconds until the budget resets | application/problem+jsonProblem |
Reservations
get/partner/v1/reservations
List your reservations in a period
Your reservations overlapping [from, to), at most 31 days and 500 reservations, by start; other partners' and the desk's never show. Scopes: reservations:read (the token needs every one). Errors: 400 VALIDATION_FAILED; 401 UNAUTHENTICATED; 403 FORBIDDEN; 429 PARTNER_RATE_LIMITED.
- Scope
reservations:read- operationId
partnerListReservations
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
from | query | string (date-time) | Yes | Start of the period, an instant in UTC; reservations overlapping [from, to) |
to | query | string (date-time) | Yes | End of the period, at most 31 days after from |
Responses
200 OK · application/json · array of Reservation
[
{
"cancelReason": "string",
"cancelledAt": "2026-10-10T17:00:00Z",
"charge": {
"amount": 120000,
"currency": "EGP"
},
"checkedInAt": "2026-10-10T17:00:00Z",
"courtId": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31",
"createdAt": "2026-10-10T17:00:00Z",
"customer": {
"name": "Omar Hassan",
"phone": "+201001234567"
},
"end": "2026-10-10T17:00:00Z",
"externalRef": "kb_8f2c41",
"id": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31",
"payment": {
"collected": {
"amount": 120000,
"currency": "EGP"
},
"method": "PAY_AT_VENUE",
"packageCreditId": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31"
},
"price": {
"amount": 120000,
"currency": "EGP"
},
"start": "2026-10-10T17:00:00Z",
"status": "CONFIRMED",
"venueId": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31"
}
]Errors
Problem details (application/problem+json) with a stable code. Each code is explained under Errors, in Arabic and English.
| Status | Description | Content type |
|---|---|---|
400 | The request is invalid: VALIDATION_FAILED (with errors per field) | application/problem+jsonProblem |
401 | UNAUTHENTICATED: no token, an expired or invalid one, or a suspended partner | application/problem+jsonProblem |
403 | FORBIDDEN: the token lacks a scope this operation needs | application/problem+jsonProblem |
429 | PARTNER_RATE_LIMITED: over your per-minute budgetRetry-After (integer (int32)): Seconds until the budget resets | application/problem+jsonProblem |
post/partner/v1/reservations
Book a court for your player
Confirmed at once, or COURT_TAKEN when the court is booked then (the database refuses double bookings). Pay at the venue (the desk collects the charge), prepaid by you (you collected; you owe the venue the charge on your statement) or with the player's package (customer.phoneVerified must be true; its minutes are taken now and come back on cancellation). The venue's desk sees the player's name and phone. Sessions are 60, 90 or 120 minutes from a half hour, inside opening hours, up to 30 days ahead. Scopes: reservations:write (the token needs every one). Idempotent: send a unique Idempotency-Key (yours alone, up to 80 characters); a retry with the same key returns the first result instead of creating another. Errors: 400 VALIDATION_FAILED, PHONE_INVALID, COURT_INVALID, COURT_SLOT_NOT_BOOKABLE, COURT_PAYMENT_INVALID, PARTNER_PHONE_NOT_VERIFIED; 401 UNAUTHENTICATED; 403 FORBIDDEN; 404 VENUE_NOT_FOUND, COURT_NOT_FOUND; 409 COURT_TAKEN, EXTERNAL_REF_IN_USE, VENUE_NOT_TAKING_BOOKINGS, COURT_PASS_NOT_USABLE, COURT_RESERVATION_STATE_INVALID; 429 PARTNER_RATE_LIMITED.
- Scope
reservations:write- operationId
partnerBook
Needs an Idempotency-Key header
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
Idempotency-Key | header | string | Yes | Your unique key for this create (up to 80 characters); a retry with the same key returns the first result |
Request body
Content type: application/json · PartnerBookingRequest
{
"courtId": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31",
"customer": {
"name": "Omar Hassan",
"phone": "+201001234567",
"phoneVerified": true
},
"externalRef": "kb_8f2c41",
"minutes": 90,
"payment": {
"collected": {
"amount": 120000,
"currency": "EGP"
},
"method": "PAY_AT_VENUE",
"packageCreditId": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31"
},
"start": "2026-10-10T17:00:00Z",
"venueId": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31"
}Responses
201 Created · application/json · Reservation
{
"cancelReason": "string",
"cancelledAt": "2026-10-10T17:00:00Z",
"charge": {
"amount": 120000,
"currency": "EGP"
},
"checkedInAt": "2026-10-10T17:00:00Z",
"courtId": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31",
"createdAt": "2026-10-10T17:00:00Z",
"customer": {
"name": "Omar Hassan",
"phone": "+201001234567"
},
"end": "2026-10-10T17:00:00Z",
"externalRef": "kb_8f2c41",
"id": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31",
"payment": {
"collected": {
"amount": 120000,
"currency": "EGP"
},
"method": "PAY_AT_VENUE",
"packageCreditId": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31"
},
"price": {
"amount": 120000,
"currency": "EGP"
},
"start": "2026-10-10T17:00:00Z",
"status": "CONFIRMED",
"venueId": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31"
}Errors
Problem details (application/problem+json) with a stable code. Each code is explained under Errors, in Arabic and English.
| Status | Description | Content type |
|---|---|---|
400 | The request is invalid: VALIDATION_FAILED, PHONE_INVALID, COURT_INVALID, COURT_SLOT_NOT_BOOKABLE, COURT_PAYMENT_INVALID, PARTNER_PHONE_NOT_VERIFIED (a package payment without customer.phoneVerified true) (with errors per field) | application/problem+jsonProblem |
401 | UNAUTHENTICATED: no token, an expired or invalid one, or a suspended partner | application/problem+jsonProblem |
403 | FORBIDDEN: the token lacks a scope this operation needs | application/problem+jsonProblem |
404 | Not found, or not yours to see (the same answer): VENUE_NOT_FOUND, COURT_NOT_FOUND | application/problem+jsonProblem |
409 | Conflict: COURT_TAKEN, EXTERNAL_REF_IN_USE, VENUE_NOT_TAKING_BOOKINGS, COURT_PASS_NOT_USABLE, COURT_RESERVATION_STATE_INVALID (the Idempotency-Key was used for another request) | application/problem+jsonProblem |
429 | PARTNER_RATE_LIMITED: over your per-minute budgetRetry-After (integer (int32)): Seconds until the budget resets | application/problem+jsonProblem |
get/partner/v1/reservations/{reservationId}
Get one of your reservations
One reservation you made, with its status, price, charge and payment; another partner's is a 404. Scopes: reservations:read (the token needs every one). Errors: 401 UNAUTHENTICATED; 403 FORBIDDEN; 404 COURT_RESERVATION_NOT_FOUND; 429 PARTNER_RATE_LIMITED.
- Scope
reservations:read- operationId
partnerGetReservation
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
reservationId | path | string (uuid) | Yes | The reservation |
Responses
200 OK · application/json · Reservation
{
"cancelReason": "string",
"cancelledAt": "2026-10-10T17:00:00Z",
"charge": {
"amount": 120000,
"currency": "EGP"
},
"checkedInAt": "2026-10-10T17:00:00Z",
"courtId": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31",
"createdAt": "2026-10-10T17:00:00Z",
"customer": {
"name": "Omar Hassan",
"phone": "+201001234567"
},
"end": "2026-10-10T17:00:00Z",
"externalRef": "kb_8f2c41",
"id": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31",
"payment": {
"collected": {
"amount": 120000,
"currency": "EGP"
},
"method": "PAY_AT_VENUE",
"packageCreditId": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31"
},
"price": {
"amount": 120000,
"currency": "EGP"
},
"start": "2026-10-10T17:00:00Z",
"status": "CONFIRMED",
"venueId": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31"
}Errors
Problem details (application/problem+json) with a stable code. Each code is explained under Errors, in Arabic and English.
| Status | Description | Content type |
|---|---|---|
401 | UNAUTHENTICATED: no token, an expired or invalid one, or a suspended partner | application/problem+jsonProblem |
403 | FORBIDDEN: the token lacks a scope this operation needs | application/problem+jsonProblem |
404 | Not found, or not yours to see (the same answer): COURT_RESERVATION_NOT_FOUND | application/problem+jsonProblem |
429 | PARTNER_RATE_LIMITED: over your per-minute budgetRetry-After (integer (int32)): Seconds until the budget resets | application/problem+jsonProblem |
post/partner/v1/reservations/{reservationId}/cancel
Cancel one of your reservations
Free of charge until the venue's cancellation cutoff (Venue.cancellationHours before the start) and before the player checks in; after that only the venue can cancel. Package minutes come back, and the venue's owner is told. A reservation that is no longer confirmed can't be cancelled again. Scopes: reservations:write (the token needs every one). Errors: 401 UNAUTHENTICATED; 403 FORBIDDEN; 404 COURT_RESERVATION_NOT_FOUND; 409 COURT_RESERVATION_NOT_CANCELLABLE; 429 PARTNER_RATE_LIMITED.
- Scope
reservations:write- operationId
partnerCancelReservation
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
reservationId | path | string (uuid) | Yes | The reservation |
Responses
200 OK · application/json · Reservation
{
"cancelReason": "string",
"cancelledAt": "2026-10-10T17:00:00Z",
"charge": {
"amount": 120000,
"currency": "EGP"
},
"checkedInAt": "2026-10-10T17:00:00Z",
"courtId": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31",
"createdAt": "2026-10-10T17:00:00Z",
"customer": {
"name": "Omar Hassan",
"phone": "+201001234567"
},
"end": "2026-10-10T17:00:00Z",
"externalRef": "kb_8f2c41",
"id": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31",
"payment": {
"collected": {
"amount": 120000,
"currency": "EGP"
},
"method": "PAY_AT_VENUE",
"packageCreditId": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31"
},
"price": {
"amount": 120000,
"currency": "EGP"
},
"start": "2026-10-10T17:00:00Z",
"status": "CONFIRMED",
"venueId": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31"
}Errors
Problem details (application/problem+json) with a stable code. Each code is explained under Errors, in Arabic and English.
| Status | Description | Content type |
|---|---|---|
401 | UNAUTHENTICATED: no token, an expired or invalid one, or a suspended partner | application/problem+jsonProblem |
403 | FORBIDDEN: the token lacks a scope this operation needs | application/problem+jsonProblem |
404 | Not found, or not yours to see (the same answer): COURT_RESERVATION_NOT_FOUND | application/problem+jsonProblem |
409 | Conflict: COURT_RESERVATION_NOT_CANCELLABLE | application/problem+jsonProblem |
429 | PARTNER_RATE_LIMITED: over your per-minute budgetRetry-After (integer (int32)): Seconds until the budget resets | application/problem+jsonProblem |
Reviews
get/partner/v1/reservations/{reservationId}/review
Get the review of your reservation
The review your player wrote for a reservation you made, with the venue owner's reply when there is one. Scopes: reservations:read (the token needs every one). Errors: 401 UNAUTHENTICATED; 403 FORBIDDEN; 404 COURT_RESERVATION_NOT_FOUND, COURT_REVIEW_NOT_FOUND; 429 PARTNER_RATE_LIMITED.
- Scope
reservations:read- operationId
partnerGetReservationReview
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
reservationId | path | string (uuid) | Yes | The reservation |
Responses
200 OK · application/json · PartnerReview
{
"authorName": "Omar H.",
"comment": "Great glass and new turf.",
"courtId": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31",
"createdAt": "2026-10-10T17:00:00Z",
"id": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31",
"repliedAt": "2026-10-10T17:00:00Z",
"reply": "Thanks, see you again!",
"reservationId": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31",
"scores": {
"cleanliness": 1,
"lighting": 1,
"overall": 1,
"surface": 1
},
"status": "string",
"venueId": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31"
}Errors
Problem details (application/problem+json) with a stable code. Each code is explained under Errors, in Arabic and English.
| Status | Description | Content type |
|---|---|---|
401 | UNAUTHENTICATED: no token, an expired or invalid one, or a suspended partner | application/problem+jsonProblem |
403 | FORBIDDEN: the token lacks a scope this operation needs | application/problem+jsonProblem |
404 | Not found, or not yours to see (the same answer): COURT_RESERVATION_NOT_FOUND, COURT_REVIEW_NOT_FOUND | application/problem+jsonProblem |
429 | PARTNER_RATE_LIMITED: over your per-minute budgetRetry-After (integer (int32)): Seconds until the budget resets | application/problem+jsonProblem |
post/partner/v1/reservations/{reservationId}/review
Review a reservation for your player
Your player's stars and words about the court of a reservation you made, once it was played (completed, or confirmed past its end), within 14 days of its end, once. Published at once; sending the same review again returns it, a different one is COURT_REVIEW_EXISTS. You get review.replied when the owner answers. Scopes: reviews:write (the token needs every one). Errors: 400 VALIDATION_FAILED, COURT_REVIEW_INVALID; 401 UNAUTHENTICATED; 403 FORBIDDEN; 404 COURT_RESERVATION_NOT_FOUND; 409 COURT_REVIEW_NOT_ALLOWED, COURT_REVIEW_EXISTS; 429 PARTNER_RATE_LIMITED.
- Scope
reviews:write- operationId
partnerReviewReservation
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
reservationId | path | string (uuid) | Yes | The reservation |
Request body
Content type: application/json · PartnerReviewRequest
{
"cleanliness": 1,
"comment": "Great glass and new turf.",
"lighting": 1,
"overall": 1,
"surface": 1
}Responses
201 Created · application/json · PartnerReview
{
"authorName": "Omar H.",
"comment": "Great glass and new turf.",
"courtId": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31",
"createdAt": "2026-10-10T17:00:00Z",
"id": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31",
"repliedAt": "2026-10-10T17:00:00Z",
"reply": "Thanks, see you again!",
"reservationId": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31",
"scores": {
"cleanliness": 1,
"lighting": 1,
"overall": 1,
"surface": 1
},
"status": "string",
"venueId": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31"
}Errors
Problem details (application/problem+json) with a stable code. Each code is explained under Errors, in Arabic and English.
| Status | Description | Content type |
|---|---|---|
400 | The request is invalid: VALIDATION_FAILED, COURT_REVIEW_INVALID (with errors per field) | application/problem+jsonProblem |
401 | UNAUTHENTICATED: no token, an expired or invalid one, or a suspended partner | application/problem+jsonProblem |
403 | FORBIDDEN: the token lacks a scope this operation needs | application/problem+jsonProblem |
404 | Not found, or not yours to see (the same answer): COURT_RESERVATION_NOT_FOUND | application/problem+jsonProblem |
409 | Conflict: COURT_REVIEW_NOT_ALLOWED, COURT_REVIEW_EXISTS | application/problem+jsonProblem |
429 | PARTNER_RATE_LIMITED: over your per-minute budgetRetry-After (integer (int32)): Seconds until the budget resets | application/problem+jsonProblem |
Safety reports
post/partner/v1/player-safety-reports
List a player's safety reports through you
The reports your player filed through you, newest first, found by the phone you verified (in the body, never the URL). Continue with before and beforeId from the last item. Scopes: safety_reports:read (the token needs every one). Errors: 400 VALIDATION_FAILED, PHONE_INVALID; 401 UNAUTHENTICATED; 403 FORBIDDEN; 429 PARTNER_RATE_LIMITED.
- Scope
safety_reports:read- operationId
partnerPlayerSafetyReports
Request body
Content type: application/json · PlayerReportsRequest
{
"before": "2026-10-10T17:00:00Z",
"beforeId": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31",
"limit": 1,
"phone": "+201001234567"
}Responses
200 OK · application/json · array of PartnerSafetyReport
[
{
"courtId": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31",
"courtName": {
"ar": "string",
"en": "string"
},
"createdAt": "2026-10-10T17:00:00Z",
"description": "A glass panel by the door is loose.",
"id": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31",
"occurredAt": "2026-10-10T17:00:00Z",
"photoUrls": [
"string"
],
"resolutionNote": "string",
"resolvedAt": "2026-10-10T17:00:00Z",
"status": "string",
"type": "string",
"venueId": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31",
"venueName": {
"ar": "string",
"en": "string"
}
}
]Errors
Problem details (application/problem+json) with a stable code. Each code is explained under Errors, in Arabic and English.
| Status | Description | Content type |
|---|---|---|
400 | The request is invalid: VALIDATION_FAILED, PHONE_INVALID (with errors per field) | application/problem+jsonProblem |
401 | UNAUTHENTICATED: no token, an expired or invalid one, or a suspended partner | application/problem+jsonProblem |
403 | FORBIDDEN: the token lacks a scope this operation needs | application/problem+jsonProblem |
429 | PARTNER_RATE_LIMITED: over your per-minute budgetRetry-After (integer (int32)): Seconds until the budget resets | application/problem+jsonProblem |
post/partner/v1/safety-reports
File a safety report for your player
Your player reports a safety problem on a court (a slippery surface, broken glass, an injury); the venue is told at once and never learns who reported. No medical details or names of the injured. At most 5 a day per player through you. You get safety_report.resolved when the venue fixes it. Scopes: safety_reports:write (the token needs every one). Idempotent: send a unique Idempotency-Key (yours alone, up to 80 characters); a retry with the same key returns the first result instead of creating another. Errors: 400 VALIDATION_FAILED, PHONE_INVALID, SAFETY_REPORT_INVALID; 401 UNAUTHENTICATED; 403 FORBIDDEN; 404 VENUE_NOT_FOUND, COURT_NOT_FOUND; 429 PARTNER_RATE_LIMITED, TOO_MANY_SAFETY_REPORTS.
- Scope
safety_reports:write- operationId
partnerFileSafetyReport
Needs an Idempotency-Key header
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
Idempotency-Key | header | string | Yes | Your unique key for this create (up to 80 characters); a retry with the same key returns the first result |
Request body
Content type: application/json · PartnerSafetyReportRequest
{
"courtId": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31",
"description": "A glass panel by the door is loose.",
"occurredAt": "2026-10-10T17:00:00Z",
"phone": "+201001234567",
"type": "INJURY",
"venueId": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31"
}Responses
201 Created · application/json · PartnerSafetyReport
{
"courtId": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31",
"courtName": {
"ar": "string",
"en": "string"
},
"createdAt": "2026-10-10T17:00:00Z",
"description": "A glass panel by the door is loose.",
"id": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31",
"occurredAt": "2026-10-10T17:00:00Z",
"photoUrls": [
"string"
],
"resolutionNote": "string",
"resolvedAt": "2026-10-10T17:00:00Z",
"status": "string",
"type": "string",
"venueId": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31",
"venueName": {
"ar": "string",
"en": "string"
}
}Errors
Problem details (application/problem+json) with a stable code. Each code is explained under Errors, in Arabic and English.
| Status | Description | Content type |
|---|---|---|
400 | The request is invalid: VALIDATION_FAILED, PHONE_INVALID, SAFETY_REPORT_INVALID (with errors per field) | application/problem+jsonProblem |
401 | UNAUTHENTICATED: no token, an expired or invalid one, or a suspended partner | application/problem+jsonProblem |
403 | FORBIDDEN: the token lacks a scope this operation needs | application/problem+jsonProblem |
404 | Not found, or not yours to see (the same answer): VENUE_NOT_FOUND, COURT_NOT_FOUND | application/problem+jsonProblem |
429 | PARTNER_RATE_LIMITED: over your per-minute budget; or TOO_MANY_SAFETY_REPORTS (5 a day per player)Retry-After (integer (int32)): Seconds until the budget resets | application/problem+jsonProblem |
post/partner/v1/safety-reports/{reportId}/photos
Add a photo to a safety report
A photo of the problem while the report is open: JPEG, PNG or WebP up to 5 MB, at most 3 per report. Stored in the private bucket without its metadata (location, camera) and shown only through links that expire. Scopes: safety_reports:write (the token needs every one). Errors: 400 FILE_REJECTED; 401 UNAUTHENTICATED; 403 FORBIDDEN; 404 SAFETY_REPORT_NOT_FOUND; 409 SAFETY_REPORT_STATE_INVALID; 429 PARTNER_RATE_LIMITED.
- Scope
safety_reports:write- operationId
partnerAddSafetyReportPhoto
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
reportId | path | string (uuid) | Yes | The safety report |
Request body
Content type: multipart/form-data
| Name | Type | Required | Description |
|---|---|---|---|
file | string (binary) | Yes |
--boundary
Content-Disposition: form-data; name="file"; filename="court.jpg"
Content-Type: image/jpeg
<file bytes>Responses
200 OK · application/json · PartnerSafetyReport
{
"courtId": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31",
"courtName": {
"ar": "string",
"en": "string"
},
"createdAt": "2026-10-10T17:00:00Z",
"description": "A glass panel by the door is loose.",
"id": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31",
"occurredAt": "2026-10-10T17:00:00Z",
"photoUrls": [
"string"
],
"resolutionNote": "string",
"resolvedAt": "2026-10-10T17:00:00Z",
"status": "string",
"type": "string",
"venueId": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31",
"venueName": {
"ar": "string",
"en": "string"
}
}Errors
Problem details (application/problem+json) with a stable code. Each code is explained under Errors, in Arabic and English.
| Status | Description | Content type |
|---|---|---|
400 | The request is invalid: FILE_REJECTED | application/problem+jsonProblem |
401 | UNAUTHENTICATED: no token, an expired or invalid one, or a suspended partner | application/problem+jsonProblem |
403 | FORBIDDEN: the token lacks a scope this operation needs | application/problem+jsonProblem |
404 | Not found, or not yours to see (the same answer): SAFETY_REPORT_NOT_FOUND | application/problem+jsonProblem |
409 | Conflict: SAFETY_REPORT_STATE_INVALID (resolved, or 3 photos already) | application/problem+jsonProblem |
429 | PARTNER_RATE_LIMITED: over your per-minute budgetRetry-After (integer (int32)): Seconds until the budget resets | application/problem+jsonProblem |
Player data
post/partner/v1/players/erasure
Forward a player's erasure request
For a player who asked you to delete their data (PDPL, ADR 0014): your reservations lose their name and phone, your reviews lose their words (the stars stay), your safety reports are unlinked from them. Only what came through you; amounts stay for the statements. Idempotent: zeros once done. Refused while one of your bookings for them is still to come. Scopes: players:erase (the token needs every one). Errors: 400 VALIDATION_FAILED, PHONE_INVALID; 401 UNAUTHENTICATED; 403 FORBIDDEN; 409 CUSTOMER_HAS_OPEN_COMMITMENTS; 429 PARTNER_RATE_LIMITED.
- Scope
players:erase- operationId
partnerErasePlayer
Request body
Content type: application/json · PlayerErasureRequest
{
"phone": "+201001234567"
}Responses
200 OK · application/json · PlayerErasureResponse
{
"reservations": 1,
"reviews": 1,
"safetyReports": 1
}Errors
Problem details (application/problem+json) with a stable code. Each code is explained under Errors, in Arabic and English.
| Status | Description | Content type |
|---|---|---|
400 | The request is invalid: VALIDATION_FAILED, PHONE_INVALID (with errors per field) | application/problem+jsonProblem |
401 | UNAUTHENTICATED: no token, an expired or invalid one, or a suspended partner | application/problem+jsonProblem |
403 | FORBIDDEN: the token lacks a scope this operation needs | application/problem+jsonProblem |
409 | Conflict: CUSTOMER_HAS_OPEN_COMMITMENTS (one of your bookings for the player is still to come) | application/problem+jsonProblem |
429 | PARTNER_RATE_LIMITED: over your per-minute budgetRetry-After (integer (int32)): Seconds until the budget resets | application/problem+jsonProblem |
Webhook
Ezaz posts these events to the URL you set here. Getting started explains each one, the payload and how to check its signature:
reservation.createdreservation.checked_inreservation.cancelledreservation.no_showreservation.completedreview.repliedsafety_report.resolved
Ignore event types you don't know, and still answer them with 2xx so they aren't retried: new types come in minor versions, as reservation.checked_in did in 1.2.0.
get/partner/v1/webhook
Get your webhook
Where your events are posted; the secret is not shown again (set the webhook to get a new one). Scopes: webhooks:manage (the token needs every one). Errors: 401 UNAUTHENTICATED; 403 FORBIDDEN; 429 PARTNER_RATE_LIMITED.
- Scope
webhooks:manage- operationId
partnerGetWebhook
Responses
200 OK · application/json · PartnerWebhookResponse
{
"secret": "whsec_…",
"url": "https://partner.example/ezaz/webhooks"
}Errors
Problem details (application/problem+json) with a stable code. Each code is explained under Errors, in Arabic and English.
| Status | Description | Content type |
|---|---|---|
401 | UNAUTHENTICATED: no token, an expired or invalid one, or a suspended partner | application/problem+jsonProblem |
403 | FORBIDDEN: the token lacks a scope this operation needs | application/problem+jsonProblem |
429 | PARTNER_RATE_LIMITED: over your per-minute budgetRetry-After (integer (int32)): Seconds until the budget resets | application/problem+jsonProblem |
put/partner/v1/webhook
Set or remove your webhook
Events (reservation changes, review replies, resolved safety reports) are posted to this public https URL, signed with HMAC-SHA256 in Ezaz-Signature, and retried for a day. Setting it returns a new signing secret; null removes it. Scopes: webhooks:manage (the token needs every one). Errors: 400 VALIDATION_FAILED, PARTNER_WEBHOOK_URL_INVALID; 401 UNAUTHENTICATED; 403 FORBIDDEN; 429 PARTNER_RATE_LIMITED.
- Scope
webhooks:manage- operationId
partnerSetWebhook
Request body
Content type: application/json · PartnerWebhookRequest
{
"url": "https://partner.example/ezaz/webhooks"
}Responses
200 OK · application/json · PartnerWebhookResponse
{
"secret": "whsec_…",
"url": "https://partner.example/ezaz/webhooks"
}Errors
Problem details (application/problem+json) with a stable code. Each code is explained under Errors, in Arabic and English.
| Status | Description | Content type |
|---|---|---|
400 | The request is invalid: VALIDATION_FAILED, PARTNER_WEBHOOK_URL_INVALID (with errors per field) | application/problem+jsonProblem |
401 | UNAUTHENTICATED: no token, an expired or invalid one, or a suspended partner | application/problem+jsonProblem |
403 | FORBIDDEN: the token lacks a scope this operation needs | application/problem+jsonProblem |
429 | PARTNER_RATE_LIMITED: over your per-minute budgetRetry-After (integer (int32)): Seconds until the budget resets | application/problem+jsonProblem |
Schemas
Area
An Egyptian area
| Name | Type | Required | Description |
|---|---|---|---|
code | string | No | Stable area code, e.g. NEW_CAIRO |
name | LocalizedText | No | The area's name |
Court
A court in a venue list
| Name | Type | Required | Description |
|---|---|---|---|
courtId | string (uuid) | No | The court |
environment | string | No | INDOOR, OUTDOOR or COVERED (outdoor under a roof) |
kind | string | No | INDOOR or OUTDOOR |
name | LocalizedText | No | Name in Arabic and English (either may be missing) |
CourtDetail
A court as players see it; facts are null when the venue hasn't said
| Name | Type | Required | Description |
|---|---|---|---|
courtId | string (uuid) | No | The court |
environment | string | No | INDOOR, OUTDOOR or COVERED (outdoor under a roof) |
kind | string | No | INDOOR or OUTDOOR |
lastRenovatedOn | string (date) | No | When it was last renovated (Cairo date) |
latestReviews | array of Review | No | Newest published reviews, on a single court only; null in lists |
lighting | string | No | LED, HALOGEN or NONE; null when not said |
name | LocalizedText | No | Name in Arabic and English (either may be missing) |
openedOn | string (date) | No | When the court opened (Cairo date) |
photoUrls | array of string | No | Public photo URLs, oldest first |
rating | Rating | No | The average of published reviews, from 3 reviews |
renovationNote | string | No | What the renovation was |
safety | Safety | No | Open safety issues and when the venue last resolved one; never the reports |
size | string | No | STANDARD_DOUBLES or SINGLES; null when not said |
surface | string | No | ARTIFICIAL_GRASS_SAND_FILLED, ARTIFICIAL_GRASS_NON_SAND, TEXTILE, CONCRETE_ACRYLIC or OTHER; null when not said |
turfBrand | string | No | The grass or turf brand or model |
venueId | string (uuid) | No | The venue |
walls | string | No | GLASS_PANORAMIC, GLASS_STANDARD, MESH_ONLY or CONCRETE_WALLS; null when not said |
CourtSlots
One court's free slots
| Name | Type | Required | Description |
|---|---|---|---|
courtId | string (uuid) | No | The court |
slots | array of Slot | No | Free slots of the requested length, by start |
Customer
Your player on a reservation
| Name | Type | Required | Description |
|---|---|---|---|
name | string | No | The player's name as you sent it |
phone | string | No | The player's phone as you verified it (E.164) |
LocalizedText
Text in Arabic and English
| Name | Type | Required | Description |
|---|---|---|---|
ar | string | No | Arabic text |
en | string | No | English text |
Money
An amount in integer piasters
| Name | Type | Required | Description |
|---|---|---|---|
amount | integer (int64) | No | Integer piasters (1 EGP = 100 piasters); never a fraction |
currency | "EGP" | No | Always EGP |
PartnerBookingRequest
A booking for your player
| Name | Type | Required | Description |
|---|---|---|---|
courtId | string (uuid) | Yes | The court |
customer | PartnerCustomerRequest | Yes | Your player: name and verified phone; the venue's desk sees both |
externalRef | string | No | Your own reference (e.g. your booking id), echoed back and in webhooks; at most one live reservation per referencemaxLength 80 |
minutes | integer (int32) | Yes | Session length: 60, 90 or 120 |
payment | PartnerPaymentRequest | Yes | Who collects the charge |
start | string (date-time) | Yes | Start, an instant in UTC (ISO-8601) |
venueId | string (uuid) | Yes | The venue |
PartnerCustomerRequest
Your player: name and the phone you verified
| Name | Type | Required | Description |
|---|---|---|---|
name | string | Yes | The player's name, shown to the venue's deskmaxLength 120 |
phone | string | Yes | The player's mobile as you verified it, E.164 or any common Egyptian format; it goes in bodies only, never in URLsmaxLength 20 |
phoneVerified | boolean | No | Your attestation that the player proved this phone to you (for example with a one-time code). Required true to pay with a package (PACKAGE); recorded with the booking |
PartnerPaymentRequest
How the booking is paid
| Name | Type | Required | Description |
|---|---|---|---|
collected | Money | No | What you collected from the player (PREPAID_BY_PARTNER only); informational |
method | "PAY_AT_VENUE" | "PREPAID_BY_PARTNER" | "PACKAGE" | Yes | PAY_AT_VENUE (the desk collects), PREPAID_BY_PARTNER (you collected and owe the venue the charge) or PACKAGE (the player's package minutes pay) |
packageCreditId | string (uuid) | No | The player's package at the venue that pays (PACKAGE only), from player-passes |
PartnerReview
A review of a reservation you made
| Name | Type | Required | Description |
|---|---|---|---|
authorName | string | No | First name and last initial ("Mona A."), never the full name or phone |
comment | string | No | The player's words, up to 500 characters |
courtId | string (uuid) | No | The court |
createdAt | string (date-time) | No | When it was created (UTC) |
id | string (uuid) | No | Stable identifier |
repliedAt | string (date-time) | No | When the venue replied (UTC) |
reply | string | No | The venue owner's one public reply |
reservationId | string (uuid) | No | The reservation |
scores | Scores | No | The stars given |
status | string | No | PUBLISHED or HIDDEN (by Ezaz support) |
venueId | string (uuid) | No | The venue |
PartnerReviewRequest
Your player's stars and words
| Name | Type | Required | Description |
|---|---|---|---|
cleanliness | integer (int32) | No | Stars for the cleanliness, 1 to 5; null when not ratedmin 1 · max 5 |
comment | string | No | Optional, up to 500 charactersmaxLength 500 |
lighting | integer (int32) | No | Stars for the lighting, 1 to 5; null when not ratedmin 1 · max 5 |
overall | integer (int32) | Yes | Overall stars, 1 to 5min 1 · max 5 |
surface | integer (int32) | No | Stars for the surface, 1 to 5; null when not ratedmin 1 · max 5 |
PartnerSafetyReport
A safety report your player filed
| Name | Type | Required | Description |
|---|---|---|---|
courtId | string (uuid) | No | The court |
courtName | LocalizedText | No | The court's name |
createdAt | string (date-time) | No | When it was created (UTC) |
description | string | No | What is wrong with the court, as the player wrote it |
id | string (uuid) | No | Stable identifier |
occurredAt | string (date-time) | No | When it happened (UTC) |
photoUrls | array of string | No | Signed photo links, valid for 10 minutes |
resolutionNote | string | No | How the venue fixed it |
resolvedAt | string (date-time) | No | When the venue resolved it (UTC) |
status | string | No | OPEN, or RESOLVED by the venue |
type | string | No | INJURY, SLIPPERY_SURFACE, BROKEN_GLASS_OR_NET, LIGHTING or OTHER |
venueId | string (uuid) | No | The venue |
venueName | LocalizedText | No | The venue's name |
PartnerSafetyReportRequest
A safety problem on a court, without medical details or names
| Name | Type | Required | Description |
|---|---|---|---|
courtId | string (uuid) | Yes | The court |
description | string | Yes | What is wrong with the court, in up to 500 characters. Don't include medical details, diagnoses or names of anyone injured.maxLength 500 |
occurredAt | string (date-time) | Yes | When it happened, within the last 30 days (UTC) |
phone | string | Yes | The player's mobile as you verified it; the venue never learns who reportedmaxLength 20 |
type | "INJURY" | "SLIPPERY_SURFACE" | "BROKEN_GLASS_OR_NET" | "LIGHTING" | "OTHER" | Yes | INJURY, SLIPPERY_SURFACE, BROKEN_GLASS_OR_NET, LIGHTING or OTHER |
venueId | string (uuid) | Yes | The venue |
PartnerToken
An access token (RFC 6749 §5.1)
| Name | Type | Required | Description |
|---|---|---|---|
access_token | string | Yes | Send as Authorization: Bearer <token> |
expires_in | integer (int32) | Yes | Seconds it stays valid (600) |
scope | string | Yes | The scopes it carries, separated by spaces |
token_type | "Bearer" | Yes | Always Bearer |
PartnerTokenError
A token error (RFC 6749 §5.2)
| Name | Type | Required | Description |
|---|---|---|---|
error | "invalid_request" | "unsupported_grant_type" | "invalid_scope" | "invalid_client" | Yes | What went wrong |
PartnerVenuePage
A page of venues that granted you
| Name | Type | Required | Description |
|---|---|---|---|
items | array of Venue | No | This page |
nextCursor | string (uuid) | No | Pass as `after` for the next page; null on the last page |
PartnerWebhookRequest
Where to post your events
| Name | Type | Required | Description |
|---|---|---|---|
url | string | No | A public https URL; null removes the webhookmaxLength 500 |
PartnerWebhookResponse
Your webhook
| Name | Type | Required | Description |
|---|---|---|---|
secret | string | No | The signing secret (whsec_…), shown when the URL is set; check Ezaz-Signature with it |
url | string | No | Where events are posted; null when none |
Payment
How a reservation is paid
| Name | Type | Required | Description |
|---|---|---|---|
collected | Money | No | What you collected from the player (PREPAID_BY_PARTNER only); informational |
method | "PAY_AT_VENUE" | "PREPAID_BY_PARTNER" | "PACKAGE" | No | PAY_AT_VENUE (the desk collects), PREPAID_BY_PARTNER (you collected and owe the venue the charge) or PACKAGE (the player's package minutes pay) |
packageCreditId | string (uuid) | No | The player's package at the venue that pays (PACKAGE only), from player-passes |
PlayerErasureRequest
The player whose data to erase
| Name | Type | Required | Description |
|---|---|---|---|
phone | string | Yes | The player's mobile as you verified it, E.164 or any common Egyptian format; it goes in bodies only, never in URLsmaxLength 32 |
PlayerErasureResponse
What lost the player's data this time; zeros when already done
| Name | Type | Required | Description |
|---|---|---|---|
reservations | integer (int32) | No | Your reservations that lost the player's name and phone |
reviews | integer (int32) | No | Your reviews that lost the player's words (stars stay) |
safetyReports | integer (int32) | No | Your safety reports unlinked from the player |
PlayerLookupRequest
The player, by the phone you verified
| Name | Type | Required | Description |
|---|---|---|---|
phone | string | Yes | The player's mobile as you verified it, E.164 or any common Egyptian format; it goes in bodies only, never in URLsmaxLength 20 |
PlayerMembership
A membership the player holds at the venue
| Name | Type | Required | Description |
|---|---|---|---|
discountBps | integer (int32) | No | The discount on court prices, in basis points (2000 = 20 %) |
endsAt | string (date-time) | No | When it ends (UTC) |
id | string (uuid) | No | The membership |
name | LocalizedText | No | Name in Arabic and English (either may be missing) |
startsAt | string (date-time) | No | When it starts (UTC) |
PlayerPackage
A package of court minutes the player holds at the venue
| Name | Type | Required | Description |
|---|---|---|---|
expiresAt | string (date-time) | No | When it expires (UTC); a session must start before |
id | string (uuid) | No | Pass as packageCreditId to pay a reservation with it |
minutesLeft | integer (int32) | No | Court minutes left |
minutesTotal | integer (int32) | No | Court minutes bought |
name | LocalizedText | No | Name in Arabic and English (either may be missing) |
PlayerPasses
A player's packages and memberships at a venue
| Name | Type | Required | Description |
|---|---|---|---|
memberships | array of PlayerMembership | No | The player's memberships at the venue, newest first |
packages | array of PlayerPackage | No | The player's packages at the venue, newest first |
PlayerReportsRequest
The player, and where the page continues
| Name | Type | Required | Description |
|---|---|---|---|
before | string (date-time) | No | Continue after the item created at this instant (from the previous page) |
beforeId | string (uuid) | No | And with this id (ties) |
limit | integer (int32) | No | Page size, 1 to 50 (default 20)min 1 · max 50 |
phone | string | Yes | The player's mobile as you verified it, E.164 or any common Egyptian format; it goes in bodies only, never in URLsmaxLength 20 |
Problem
RFC 9457 problem details. Branch on code, which is stable; show detail, which is localized and may change
| Name | Type | Required | Description |
|---|---|---|---|
code | string | Yes | Stable error code to branch on |
detail | string | No | What happened, in the Accept-Language (ar or en), for people |
errors | array of object | No | Per field, for VALIDATION_FAILED only |
errors[].field | string | No | The field, as named in the request |
errors[].message | string | No | What is wrong with it, in the Accept-Language (ar or en) |
instance | string | No | The request path |
status | integer (int32) | Yes | The HTTP status |
title | string | No | The HTTP status's reason phrase |
type | string | No | A URI naming the problem: urn:ezaz:problem: and the code |
Quote
What a slot costs your player
| Name | Type | Required | Description |
|---|---|---|---|
charge | Money | No | What the player pays, prepaid or at the venue: the member price, or the price |
courtId | string (uuid) | No | The court |
discountBps | integer (int32) | No | The player's membership discount in basis points; 0 without one |
end | string (date-time) | No | End, an instant in UTC (ISO-8601) |
price | Money | No | The venue's list price for the session |
start | string (date-time) | No | Start, an instant in UTC (ISO-8601) |
QuoteRequest
A slot and your player's phone
| Name | Type | Required | Description |
|---|---|---|---|
courtId | string (uuid) | Yes | The court |
minutes | integer (int32) | Yes | Session length: 60, 90 or 120min 30 · max 1440 |
phone | string | Yes | The player's mobile as you verified it, E.164 or any common Egyptian format; it goes in bodies only, never in URLsmaxLength 32 |
start | string (date-time) | Yes | Start, an instant in UTC (ISO-8601) |
Rating
A court's rating from published reviews
| Name | Type | Required | Description |
|---|---|---|---|
average | number (double) | No | Overall stars to one decimal; null until there are 3 reviews |
cleanliness | number (double) | No | Average cleanliness stars; null until 3 reviews rated it |
count | integer (int32) | No | Published reviews |
lighting | number (double) | No | Average lighting stars; null until 3 reviews rated it |
surface | number (double) | No | Average surface stars; null until 3 reviews rated it |
Reservation
A court reservation you made
| Name | Type | Required | Description |
|---|---|---|---|
cancelReason | string | No | PARTNER when you cancelled, otherwise the venue's reason |
cancelledAt | string (date-time) | No | When it was cancelled (UTC) |
charge | Money | No | What the venue is owed: the list price less the player's membership discount at the venue (whoever collects it), zero when a package pays |
checkedInAt | string (date-time) | No | When the venue's desk checked the player in (UTC); null until they arrive |
courtId | string (uuid) | No | The court |
createdAt | string (date-time) | No | When it was created (UTC) |
customer | Customer | No | Your player; null once their data was erased |
end | string (date-time) | No | End, an instant in UTC (ISO-8601) |
externalRef | string | No | Your own reference (e.g. your booking id), echoed back and in webhooks; at most one live reservation per reference |
id | string (uuid) | No | Stable identifier |
payment | Payment | No | Who collects the charge |
price | Money | No | The venue's list price for the session |
start | string (date-time) | No | Start, an instant in UTC (ISO-8601) |
status | "CONFIRMED" | "CANCELLED" | "COMPLETED" | "NO_SHOW" | No | CONFIRMED, CANCELLED, COMPLETED or NO_SHOW |
venueId | string (uuid) | No | The venue |
Review
A published review
| Name | Type | Required | Description |
|---|---|---|---|
authorName | string | No | First name and last initial ("Mona A."), never the full name or phone |
cleanliness | integer (int32) | No | Stars for the cleanliness, 1 to 5; null when not rated |
comment | string | No | The player's words, up to 500 characters |
courtId | string (uuid) | No | The court |
createdAt | string (date-time) | No | When it was created (UTC) |
id | string (uuid) | No | Stable identifier |
lighting | integer (int32) | No | Stars for the lighting, 1 to 5; null when not rated |
overall | integer (int32) | No | Overall stars, 1 to 5 |
repliedAt | string (date-time) | No | When the venue replied (UTC) |
reply | string | No | The venue owner's one public reply |
surface | integer (int32) | No | Stars for the surface, 1 to 5; null when not rated |
Safety
A court's safety summary; never the reports
| Name | Type | Required | Description |
|---|---|---|---|
lastResolvedOn | string (date) | No | The Cairo date the venue last resolved one; null if never |
openIssues | integer (int32) | No | Safety reports on the court the venue hasn't resolved yet |
Scores
The stars of a review
| Name | Type | Required | Description |
|---|---|---|---|
cleanliness | integer (int32) | No | Stars for the cleanliness, 1 to 5; null when not rated |
lighting | integer (int32) | No | Stars for the lighting, 1 to 5; null when not rated |
overall | integer (int32) | No | Overall stars, 1 to 5 |
surface | integer (int32) | No | Stars for the surface, 1 to 5; null when not rated |
Slot
A free slot and its price
| Name | Type | Required | Description |
|---|---|---|---|
end | string (date-time) | No | End, an instant in UTC (ISO-8601) |
price | Money | No | The venue's list price for the session |
start | string (date-time) | No | Start, an instant in UTC (ISO-8601) |
Venue
A venue that lets you sell its courts
| Name | Type | Required | Description |
|---|---|---|---|
address | LocalizedText | No | Street address in Arabic and English |
area | Area | No | The area the venue is in |
cancellationHours | integer (int32) | No | Players cancel free of charge until this many hours before the start |
contactPhone | string | No | The venue's public number (E.164) |
courts | array of Court | No | The venue's active courts |
latitude | number (double) | No | Map location; null when not pinned |
longitude | number (double) | No | Map location; null when not pinned |
name | LocalizedText | No | Name in Arabic and English (either may be missing) |
photoUrls | array of string | No | Public photo URLs, oldest first |
venueId | string (uuid) | No | The venue |