Skip to main content

Player Cart Incidents API

Version: 1.0 Base Path: /players/me/cart-incidents Authentication: Bearer JWT (Cookie or Header)

Overview​

The Cart Incidents API allows players to report stuck or malfunctioning golf carts during their round and track the status of their reports.

Authentication​

All endpoints require a valid JWT token. The API identifies the player from the authenticated user's email.

# Cookie-based (recommended)
curl -X POST /api/players/me/cart-incidents \
--cookie "access_token=<jwt>"

# Header-based
curl -X POST /api/players/me/cart-incidents \
-H "Authorization: Bearer <jwt>"

Endpoints​

Report a Stuck Cart​

Report that your cart is stuck at a specific hole.

POST /players/me/cart-incidents

Request Body​

FieldTypeRequiredDescription
reservationIdUUIDYesYour cart reservation ID
holeNumberIntegerYesHole number (1-18)
descriptionStringNoDescription of the issue (max 500 chars)

Example Request​

{
"reservationId": "550e8400-e29b-41d4-a716-446655440000",
"holeNumber": 7,
"description": "Cart won't start after stopping at the 7th tee box"
}

Response​

{
"id": "a3bb189e-8bf9-3888-9912-ace4e6543002",
"reservationId": "550e8400-e29b-41d4-a716-446655440000",
"courseId": "c1234567-e29b-41d4-a716-446655440000",
"holeNumber": 7,
"description": "Cart won't start after stopping at the 7th tee box",
"status": "REPORTED",
"replacementCartAssigned": false,
"reportedAt": "2026-01-06T10:30:00Z",
"acknowledgedAt": null,
"resolvedAt": null
}

Errors​

StatusCodeDescription
400PLAYER_NOT_FOUNDUnable to resolve player identity
400ACTIVE_INCIDENT_EXISTSAn active incident already exists for this reservation
400COURSE_NOT_FOUNDUnable to determine course for this reservation
403NOT_YOUR_RESERVATIONYou do not have access to this cart reservation
404RESERVATION_NOT_FOUNDCart reservation not found

List My Incidents​

Get all cart incidents you have reported.

GET /players/me/cart-incidents

Query Parameters​

ParameterTypeDefaultDescription
statusString-Filter by status
limitInteger50Max results (1-100)
offsetInteger0Skip results

Status Values​

  • REPORTED - Initial report, waiting for staff
  • ACKNOWLEDGED - Staff has seen the report
  • REPLACEMENT_ASSIGNED - A replacement cart is on the way
  • RESOLVED - Issue has been resolved
  • CANCELLED - You cancelled the report

Example Request​

GET /players/me/cart-incidents?status=REPORTED&limit=10

Response​

[
{
"id": "a3bb189e-8bf9-3888-9912-ace4e6543002",
"reservationId": "550e8400-e29b-41d4-a716-446655440000",
"courseId": "c1234567-e29b-41d4-a716-446655440000",
"holeNumber": 7,
"description": "Cart won't start",
"status": "ACKNOWLEDGED",
"replacementCartAssigned": false,
"reportedAt": "2026-01-06T10:30:00Z",
"acknowledgedAt": "2026-01-06T10:32:00Z",
"resolvedAt": null
}
]

Get Incident Status​

Check the current status of a specific incident.

GET /players/me/cart-incidents/:incidentId

Path Parameters​

ParameterTypeDescription
incidentIdUUIDThe incident ID

Response​

{
"id": "a3bb189e-8bf9-3888-9912-ace4e6543002",
"reservationId": "550e8400-e29b-41d4-a716-446655440000",
"courseId": "c1234567-e29b-41d4-a716-446655440000",
"holeNumber": 7,
"description": "Cart won't start",
"status": "REPLACEMENT_ASSIGNED",
"replacementCartAssigned": true,
"reportedAt": "2026-01-06T10:30:00Z",
"acknowledgedAt": "2026-01-06T10:32:00Z",
"resolvedAt": null
}

Errors​

StatusCodeDescription
403NOT_YOUR_INCIDENTYou do not have access to this incident
404INCIDENT_NOT_FOUNDIncident not found

Cancel My Incident​

Cancel an incident you reported. Only possible if staff has not yet acknowledged it.

PATCH /players/me/cart-incidents/:incidentId/cancel

Path Parameters​

ParameterTypeDescription
incidentIdUUIDThe incident ID to cancel

Response​

{
"id": "a3bb189e-8bf9-3888-9912-ace4e6543002",
"reservationId": "550e8400-e29b-41d4-a716-446655440000",
"courseId": "c1234567-e29b-41d4-a716-446655440000",
"holeNumber": 7,
"description": "Cart won't start",
"status": "CANCELLED",
"replacementCartAssigned": false,
"reportedAt": "2026-01-06T10:30:00Z",
"acknowledgedAt": null,
"resolvedAt": "2026-01-06T10:35:00Z"
}

Errors​

StatusCodeDescription
400CANNOT_CANCELCannot cancel - already acknowledged by staff
403NOT_YOUR_INCIDENTYou do not have access to this incident
404INCIDENT_NOT_FOUNDIncident not found

Get Photo Upload URL​

Request a presigned URL to upload a photo for an incident.

POST /players/me/cart-incidents/:incidentId/photos/upload-url

Request Body​

FieldTypeRequiredDescription
filenameStringYesOriginal filename
sizeIntegerYesFile size in bytes (max 10MB)
mimeTypeStringYesMIME type (image/jpeg, image/png)

Response​

{
"uploadUrl": "https://s3.amazonaws.com/...",
"key": "incidents/abc123/photo-001.jpg"
}

Confirm Photo Upload​

After uploading to S3, confirm the photo to attach it to the incident.

POST /players/me/cart-incidents/:incidentId/photos

Request Body​

FieldTypeRequiredDescription
keyStringYesS3 key returned from upload-url
mimeTypeStringYesMIME type of uploaded file

Response​

{
"id": "photo-uuid",
"url": "https://...",
"uploadedAt": "2026-01-07T10:30:00Z"
}

List My Incident Photos​

Get all photos attached to an incident.

GET /players/me/cart-incidents/:incidentId/photos

Path Parameters​

ParameterTypeDescription
incidentIdUUIDThe incident ID

Response​

[
{
"id": "photo-uuid",
"url": "https://...",
"mimeType": "image/jpeg",
"uploadedAt": "2026-01-07T10:30:00Z"
}
]

Errors​

StatusCodeDescription
403NOT_YOUR_INCIDENTYou do not have access to this incident
404INCIDENT_NOT_FOUNDIncident not found

Status Flow​

    ┌─────────┐
│REPORTED │ ◄── Player reports issue
└────┬────┘
│
┌────▼────┐
│ACKNOWLEDGED│ ◄── Staff sees report
└────┬────┘
│
┌────────▼─────────┐
│REPLACEMENT_ASSIGNED│ ◄── Cart on the way
└────────┬─────────┘
│
┌────▼────┐
│RESOLVED │ ◄── Issue fixed
└─────────┘

Player can CANCEL only from REPORTED status.

Real-Time Updates​

For real-time status updates, connect to the TeeTime WebSocket gateway:

// Build WebSocket URL with auth token
const protocol = window.location.protocol === 'https:' ? 'wss' : 'ws';
const wsUrl = `${protocol}://${window.location.host}/api/ws/tee-sheet?token=${accessToken}`;
const ws = new WebSocket(wsUrl);

// Subscribe to your club's events
ws.onopen = () => {
ws.send(JSON.stringify({
event: 'subscribe',
data: { room: `club:${clubId}` }
}));
};

// Listen for incident updates
ws.onmessage = (message) => {
const { event } = JSON.parse(message.data);
if (event?.type?.startsWith('cart.incident')) {
console.log('Incident update:', event.type, event.data);
}
};

Event Types​

EventDescription
cart.incident.reportedNew incident reported
cart.incident.acknowledgedStaff acknowledged the incident
cart.incident.replacement-assignedReplacement cart dispatched
cart.incident.resolvedIncident resolved
cart.incident.escalatedSLA breach - incident escalated

Rate Limits​

  • Report incident: 5 requests per minute
  • List/Get: 60 requests per minute

Support​

If you experience issues with the cart incident system, contact course staff directly or call the pro shop.