Authentication
API key authentication. Include the X-API-Key header in every request. Keys are issued by administrators; an integration-type key is bound to one golf club per key (owner_id). The target golf club is determined from the key — do not include golf_club_id in the request (no access to other clubs' data is possible).
Request header example
POST /api/integration/tee-times/sync.php HTTP/1.1
Host: en.govigolf.com
X-API-Key: YOUR_API_KEY
Content-Type: application/json
Scopes: integration:read for read operations, integration:write for write operations.
API key authentication (X-API-Key header, owner_type='golf_club' key). Handled by GolfClubAuthService. The target golf club is determined from the key (owner_id) — no need to pass golf_club_id as a parameter.
Request header example
GET /api/manage/reservations/list.php HTTP/1.1
Host: en.govigolf.com
X-API-Key: YOUR_API_KEY
Scopes (per resource): reservations:read/write / tee_times:read/write / notifications:read/write / settings:read/write / reports:read.
Integration: Tee times
Syncs tee time slots from an external system into GOVIGO (external → GOVIGO). Maximum 500 slots per request.
| Parameter | Type | Required | Description |
slots | array | Required | Array of slot objects (max 500) |
slots element fields
| Field | Type | Required | Description |
course_id | integer | Required | Course ID (must belong to your golf club) |
tee_time | string | Required | Tee time (YYYY-MM-DD HH:MM) |
total_slots | integer | Optional | Total slots (default: 4) |
available_slots | integer | Optional | Available slots (default: same as total_slots) |
status | string | Optional | open / closed / maintenance (default: open) |
plan_id | integer | Optional | Associated plan ID (must belong to your golf club) |
Request example
POST /api/integration/tee-times/sync.php HTTP/1.1
Host: en.govigolf.com
X-API-Key: YOUR_API_KEY
Content-Type: application/json
{
"slots": [
{ "course_id": 10, "tee_time": "2026-07-01 07:30", "total_slots": 4, "available_slots": 4 }
]
}
Response data fields
| Field | Type | Description |
inserted_count | integer | Number of newly created slots |
updated_count | integer | Number of updated slots |
error_count | integer | Number of failed items |
errors | array | Array of error detail messages |
Retrieves GOVIGO tee times (GOVIGO → external).
| Parameter | Type | Required | Description |
date_from | string | Required | Start date (YYYY-MM-DD) |
date_to | string | Required | End date (YYYY-MM-DD) |
course_id | integer | Optional | Filter by course |
Request example
GET /api/integration/tee-times/pull.php?date_from=2026-07-01&date_to=2026-07-07 HTTP/1.1
Host: en.govigolf.com
X-API-Key: YOUR_API_KEY
Response data fields
| Field | Type | Description |
golf_club_id | integer | Golf club ID |
date_from / date_to | string | Requested date range |
count | integer | Number of slots returned |
slots | array | Array of slot objects (see below) |
slots element fields
| Field | Type | Description |
slot_id | integer | Slot ID (GOVIGO internal ID) |
course_id | integer | Course ID |
course_name | string | Course name |
tee_time | string | Tee time (YYYY-MM-DD HH:MM) |
total_slots | integer | Total slots |
available_slots | integer | Available slots |
status | string | open / closed / maintenance |
allow_join | boolean | Join (shared booking) allowed |
plan_id | integer|null | Associated plan ID |
Reconciles the GOVIGO mirror against a full snapshot of slots for the given period from the club side (for fixing drift caused by missed webhooks, etc.). All slots are upserted and slots absent from the snapshot are swept up. Slots with no bookings are logically closed (status=closed — not physically deleted); slots that had bookings but disappeared from the snapshot are returned as conflicts (for manual resolution) rather than being closed. Closed slots are hidden from customer availability views and revert to open automatically when the club resubmits them. Intended to be run periodically by the club (e.g. nightly).
| Parameter | Type | Required | Description |
date_from / date_to | string | Required | Reconciliation period (YYYY-MM-DD) |
course_id | integer | Optional | If specified, reconcile only that course |
slots | array | Required | All slots in the period (max 2000; split into narrower periods if needed). Same fields as sync (see above) |
Request example
POST /api/integration/tee-times/reconcile.php HTTP/1.1
Host: en.govigolf.com
X-API-Key: YOUR_API_KEY
Content-Type: application/json
{
"date_from": "2026-07-01",
"date_to": "2026-07-01",
"slots": [
{ "course_id": 10, "tee_time": "2026-07-01 07:30", "total_slots": 4, "available_slots": 4 }
]
}
Response data fields
| Field | Type | Description |
inserted_count | integer | Number of newly created slots |
updated_count | integer | Number of updated slots |
closed_count | integer | Number of logically closed slots (unbooked and absent from snapshot) |
conflict_count | integer | Number of conflicts (booked and absent from snapshot) |
conflicts | array | Array of conflict slot objects (see below). Manual resolution required. |
error_count | integer | Number of processing errors |
errors | array | Array of error detail messages |
conflicts element fields
| Field | Type | Description |
tee_time_slot_id | integer | Slot ID (GOVIGO internal ID) |
course_id | integer | Course ID |
tee_time | string | Tee time (YYYY-MM-DD HH:MM) |
total_slots | integer | Total slots |
available_slots | integer | Available slots |
booked | integer | Booked count (= total - available) |
Integration: Reservations
Imports a reservation that originated in an external system into GOVIGO (external → GOVIGO). external_ref is the idempotency key; a duplicate submission with the same value returns the existing reservation and exits.
| Parameter | Type | Required | Description |
external_ref | string | Required | Reservation reference key from the external system (idempotency key to prevent duplicate imports) |
course_id | integer | Required | Course ID (must belong to your golf club) |
tee_date | string | Required | Play date (YYYY-MM-DD) |
customer_name | string | Required | Booker name |
player_count | integer | Required | Number of players (1 or more) |
tee_time | string | Optional | Tee time (HH:MM). If tee_time_slot_id is given, the slot's time is used. |
tee_time_slot_id | integer | Optional | GOVIGO slot ID. If specified, reserves inventory for the player count (409 if insufficient). |
golf_plan_id | integer | Optional | Plan ID (must belong to your golf club) |
customer_email | string | Optional | Booker email |
customer_phone | string | Optional | Booker phone number |
total_amount | integer | Optional | Total amount (VND; default: 0) |
remark | string | Optional | Remark |
options | object | Optional | Option information (arbitrary key-value) |
attendees | array | Optional | Companion list. Each element: {name (required), email?, phone?} |
Request example
POST /api/integration/reservations/receive.php HTTP/1.1
Host: en.govigolf.com
X-API-Key: YOUR_API_KEY
Content-Type: application/json
{
"external_ref": "EXT-12345",
"course_id": 10,
"tee_date": "2026-07-01",
"tee_time": "07:30",
"customer_name": "John Smith",
"customer_email": "[email protected]",
"customer_phone": "+84-90-0000-0000",
"player_count": 2,
"total_amount": 3600000
}
Response data fields
| Field | Type | Description |
reservation_id | integer | GOVIGO-assigned reservation ID |
external_ref | string | External reference key (same as request) |
status | string | pending (initial status at creation) |
duplicate | boolean | true only if the same external_ref already existed (HTTP 200) |
Reflects changes from the external system to the GOVIGO mirror (external → GOVIGO). Only specified fields are updated. Changing player count adjusts inventory by the difference (409 if insufficient slots for an increase). Use cancel.php for cancellations. Date/time changes are not allowed for slot-linked reservations (cancel and re-create instead).
| Parameter | Type | Required | Description |
external_ref | string | One required | Identify target by external reference key |
reservation_id | integer | One required | Identify target by GOVIGO reservation ID |
customer_name | string | Optional | Booker name |
customer_email | string | Optional | Booker email |
customer_phone | string | Optional | Booker phone number |
tee_date | string | Optional | Play date (YYYY-MM-DD). Not changeable for slot-linked reservations. |
tee_time | string | Optional | Tee time (HH:MM). Not changeable for slot-linked reservations. |
player_count | integer | Optional | Number of players. Adjusts slot inventory by difference if slot-linked. |
total_amount | integer | Optional | Total amount (VND) |
remark | string | Optional | Remark |
options | object | Optional | Option information |
status | integer | Optional | Only 1=reserved / 3=completed may be specified. Use cancel.php for cancellations. |
Request example
POST /api/integration/reservations/update.php HTTP/1.1
Host: en.govigolf.com
X-API-Key: YOUR_API_KEY
Content-Type: application/json
{ "external_ref": "EXT-12345", "player_count": 3, "tee_time": "08:00" }
Response data fields
| Field | Type | Description |
reservation_id | integer | ID of the updated reservation |
external_ref | string|null | External reference key |
Reflects a cancellation from the external system into the GOVIGO mirror (external → GOVIGO). Sets status to cancelled and restores slot inventory by the player count if a slot is linked. Idempotent (returns success even if already cancelled).
| Parameter | Type | Required | Description |
external_ref | string | One required | Identify target by external reference key |
reservation_id | integer | One required | Identify target by GOVIGO reservation ID |
Request example
POST /api/integration/reservations/cancel.php HTTP/1.1
Host: en.govigolf.com
X-API-Key: YOUR_API_KEY
Content-Type: application/json
{ "external_ref": "EXT-12345" }
Response data fields
| Field | Type | Description |
reservation_id | integer | ID of the cancelled reservation |
external_ref | string|null | External reference key |
status | string | cancelled |
already | boolean | true only if already cancelled |
Retrieves GOVIGO reservation data (GOVIGO → external). Default range: today to 30 days ahead.
| Parameter | Type | Required | Description |
date_from | string | Optional | Start date (YYYY-MM-DD; default: today) |
date_to | string | Optional | End date (YYYY-MM-DD; default: today + 30 days) |
status | integer | Optional | Filter by status code (see table below) |
include_attendees | boolean | Optional | true to include companion information |
Response data fields
| Field | Type | Description |
golf_club_id | integer | Golf club ID |
date_from / date_to | string | Requested date range |
count | integer | Number of reservations returned |
reservations | array | Array of reservation objects (see below) |
reservations element fields
| Field | Type | Description |
reservation_id | integer | GOVIGO reservation ID |
course_id | integer | Course ID |
course_name | string | Course name |
customer_name | string | Booker name |
customer_email | string | Booker email |
customer_phone | string | Booker phone |
tee_date | string | Play date (YYYY-MM-DD) |
tee_time | string | Tee time (HH:MM) |
player_count | integer | Number of players |
total_amount | integer | Total amount (VND) |
status | string | pending_payment / reserved / cancelled / completed |
status_code | integer | Status code (0=pending payment / 1=reserved / 2=cancelled / 3=completed) |
source | string | Booking source (api_integration etc.) |
external_ref | string|null | External reference key |
created_at | string | Created at |
updated_at | string | Updated at |
attendees | array | Only when include_attendees=true. Array of {name, email, phone} |
Integration: Webhook
Registers a URL to receive event notifications for reservations, inventory, etc.
| Parameter | Type | Required | Description |
url | string | Required | Webhook receiving URL (HTTPS required) |
events | array | Required | Event types to subscribe (reservation.created/updated/cancelled/status_changed, tee_time.updated, *) |
Request example
POST /api/integration/webhooks/subscribe.php HTTP/1.1
Host: en.govigolf.com
X-API-Key: YOUR_API_KEY
Content-Type: application/json
{ "url": "https://example.com/hook", "events": ["reservation.created", "reservation.cancelled"] }
Returns the list of registered Webhooks (no parameters; target golf club determined from the key).
Unsubscribes a registered Webhook.
| Parameter | Type | Required | Description |
subscription_id | integer | Required | Subscription ID to unsubscribe |
Sends a test event to the specified subscription.
| Parameter | Type | Required | Description |
subscription_id | integer | Required | Subscription ID to test |
Management: Reservations
Returns the reservation list for your golf club. Default: 20 per page (max 100).
| Parameter | Type | Required | Description |
status | integer | Optional | Filter by status code (see table below) |
date_from / date_to | string | Optional | Filter by play date (YYYY-MM-DD) |
search | string | Optional | Keyword search on booker name, email, or phone |
page | integer | Optional | Page number (default: 1) |
per_page | integer | Optional | Items per page (default: 20, max: 100) |
Request example
GET /api/manage/reservations/list.php?date_from=2026-07-01&date_to=2026-07-31&page=1 HTTP/1.1
Host: en.govigolf.com
X-API-Key: YOUR_API_KEY
Response data fields
| Field | Type | Description |
reservations | array | Array of reservation objects (see below) |
pagination.page | integer | Current page |
pagination.per_page | integer | Items per page |
pagination.total_count | integer | Total count |
pagination.total_pages | integer | Total pages |
pagination.has_next | boolean | Has next page |
pagination.has_prev | boolean | Has previous page |
reservations element fields
| Field | Type | Description |
id | integer | Reservation ID |
course_name | string | Course name |
customer_name | string | Booker name |
customer_email | string | Booker email |
customer_phone | string | Booker phone |
tee_date | string | Play date (YYYY-MM-DD) |
tee_time | string | Tee time (HH:MM) |
player_count | integer | Number of players |
total_amount | integer | Total amount (VND) |
status | string | Status string (see table below) |
status_code | integer | Status code (0–3, 9) |
source | string | Booking source |
remark | string | Remark |
created_at | string | Created at |
Status code reference
0 = pending_payment / 1 = reserved / 2 = cancelled / 3 = completed / 9 = cancelled (legacy)
Returns reservation details including companion information.
| Parameter | Type | Required | Description |
reservation_id | integer | Required | Reservation ID (legacy id also accepted) |
Response data.reservation fields
| Field | Type | Description |
id | integer | Reservation ID |
course_name | string | Course name |
plan_name | string|null | Plan name |
customer_name | string | Booker name |
customer_email | string | Booker email |
customer_phone | string | Booker phone |
tee_date | string | Play date (YYYY-MM-DD) |
tee_time | string | Tee time (HH:MM) |
player_count | integer | Number of players |
total_amount | integer | Total amount (VND) |
remark | string | Remark |
options | object|null | Option information |
status | string | Status string (same code reference as list) |
status_code | integer | Status code (0–3, 9) |
source | string | Booking source |
external_ref | string|null | External reference key |
created_at | string | Created at |
updated_at | string | Updated at |
attendees | array | Companion list. Each element: {id, name, email, phone} |
Updates the reservation status. status=9 is treated as a cancellation and restores slot inventory. Cancelled reservations cannot be moved to another status (409).
| Parameter | Type | Required | Description |
reservation_id | integer | Required | Reservation ID |
status | integer | Required | New status code (0–3, 9) |
memo | string | Optional | Change memo (appended to remark) |
Request example
POST /api/manage/reservations/update-status.php HTTP/1.1
Host: en.govigolf.com
X-API-Key: YOUR_API_KEY
Content-Type: application/json
{ "reservation_id": 123, "status": 1, "memo": "Confirmed" }
Response data fields
| Field | Type | Description |
reservation_id | integer | ID of the updated reservation |
old_status | string | Previous status string |
new_status | string | New status string |
Management: Tee time slots
Returns the tee time slot list for the specified date.
| Parameter | Type | Required | Description |
date | string | Required | Target date (YYYY-MM-DD) |
course_id | integer | Optional | Filter by course |
Response data fields
| Field | Type | Description |
date | string | Target date |
count | integer | Number of slots returned |
slots | array | Array of slot objects (see below) |
slots element fields
| Field | Type | Description |
id | integer | Slot ID (= slot_id) |
course_id | integer | Course ID |
course_name | string | Course name |
tee_time | string | Tee time (HH:MM) |
total_slots | integer | Total slots |
available_slots | integer | Available slots |
booked_slots | integer | Booked slots (= total - available) |
status | string | open / closed / maintenance |
allow_join | boolean | Join (shared booking) allowed |
plan_id | integer|null | Associated plan ID |
plan_name | string|null | Plan name |
Updates a single tee time slot. Returns 400 if available_slots after update would be outside the range 0–total_slots.
| Parameter | Type | Required | Description |
slot_id | integer | Required | Tee time slot ID |
total_slots | integer | Optional | Total slots (1 or more) |
available_slots | integer | Optional | Available slots (0 or more, ≤ total_slots) |
status | string | Optional | open / closed / maintenance |
allow_join | boolean | Optional | Allow join |
golf_club_plan_id | integer|null | Optional | Associated plan ID (null to unlink; must belong to your golf club) |
Response data fields
| Field | Type | Description |
slot_id | integer | ID of the updated slot |
updated | boolean | true |
Updates multiple tee time slots in one request (max 200). If any slot fails validation it is skipped and the details are returned in errors; other slots are still updated.
| Parameter | Type | Required | Description |
slots | array | Required | Array of slots to update (max 200) |
slots element fields
| Field | Type | Required | Description |
slot_id | integer | Required | Tee time slot ID |
total_slots | integer | Optional | Total slots |
available_slots | integer | Optional | Available slots |
status | string | Optional | open / closed / maintenance |
allow_join | boolean | Optional | Allow join |
Request example
POST /api/manage/tee-times/bulk-update.php HTTP/1.1
Host: en.govigolf.com
X-API-Key: YOUR_API_KEY
Content-Type: application/json
{ "slots": [ { "slot_id": 501, "available_slots": 0, "status": "closed" }, { "slot_id": 502, "available_slots": 2 } ] }
Response data fields
| Field | Type | Description |
updated_count | integer | Number of successfully updated slots |
error_count | integer | Number of skipped items |
errors | array | Array of error detail messages |
Management: Notifications
Returns the notification list in descending order of creation date.
| Parameter | Type | Required | Description |
page | integer | Optional | Page number (default: 1) |
per_page | integer | Optional | Items per page (default: 20, max: 100) |
unread_only | integer | Optional | 1 to return unread only |
Response data fields
| Field | Type | Description |
notifications | array | Array of notification objects (see below) |
pagination | object | Pagination info (same format as reservation list) |
notifications element fields
| Field | Type | Description |
id | integer | Notification ID |
type | string | Notification type (e.g. reservation.created) |
reserve_id | integer|null | Associated reservation ID |
title | string | Notification title |
body | string | Notification body |
is_read | boolean | Read flag |
created_at | string | Created at |
Marks notifications as read. Either notification_ids or all is required.
| Parameter | Type | Required | Description |
notification_ids | array | One required | Array of notification IDs to mark read (integer[]) |
all | boolean | One required | true to mark all as read |
Response data fields
| Field | Type | Description |
updated_count | integer | Number of notifications marked as read |
Returns the number of unread notifications (no parameters).
Response data fields
| Field | Type | Description |
unread_count | integer | Number of unread notifications |
Management: Settings
Retrieves golf club settings. Returns all settings as { key: value } if key is omitted.
| Parameter | Type | Required | Description |
key | string | Optional | Return only this key if specified; all keys if omitted |
Response data fields (single key)
| Field | Type | Description |
key | string | Setting key |
value | string|null | Setting value (null if not set) |
Response data fields (all keys)
| Field | Type | Description |
count | integer | Total number of setting keys |
settings | object | Object in { "key": "value", ... } format |
Updates golf club settings (UPSERT). Multiple keys can be updated at once.
| Parameter | Type | Required | Description |
settings | object | Required | Settings object in { "key": "value", ... } format |
Request example
POST /api/manage/settings/update.php HTTP/1.1
Host: en.govigolf.com
X-API-Key: YOUR_API_KEY
Content-Type: application/json
{ "settings": { "auto_confirm": "1", "cancel_deadline_days": "3" } }
Response data fields
| Field | Type | Description |
updated_count | integer | Number of setting keys updated |
settings | object | Updated settings as { "key": "value", ... } |