Changelog
Track changes, improvements, and updates to the Delivery Locker API.
Version 1.0.299 (2026-01-23)
⚠️ Breaking Changes
Webhook Payload Structure Overhaul (SD-3662)
The webhook payload structure has been updated to use a flat proto-based format instead of the previous envelope wrapper format. This is a breaking change that requires updates to your webhook handlers.
Key Changes:
- Payload Format: Changed from envelope wrapper to flat structure
- Event Type Field: Changed from
eventtoevent_typewith proto enum values - Event Type Values: Changed from dot notation to proto enum format
- New Header: Added
X-Platform-Order-Idheader to all webhook requests
Payload Structure Change
Before (Legacy Envelope Format):
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"event": "reservation.dropped_off",
"timestamp": "2025-06-13T10:30:00Z",
"data": {
"reservation_id": "res_abc123",
"platform_order_id": "order_12345",
"machine_id": "kf_tangerang_001",
"cell_description": "A03",
"status": "DROPPED_OFF"
}
}
After (Flat Proto Format):
{
"event_id": "evt_550e8400-e29b-41d4-a716-446655440000",
"idempotency_key": "idem_abc123def456",
"event_time_unix_timestamp": 1718271000,
"event_time_timestamp": "2025-06-13T10:30:00Z",
"platform_order_id": "order_12345",
"reservation_id": "res_abc123",
"event_type": "EVENT_TYPE_DROPOFF",
"drop_off_event": {
"source_type": "SOURCE_TYPE_MACHINE",
"cell": {
"description": "A03",
"cell_id": "cell_kf_tan_001_a03"
},
"machine": {
"machine_id": "kf_tangerang_001",
"name": "Tangerang Station Locker",
"location": "Tangerang Train Station"
}
}
}
Event Type Value Changes
| Old Format | New Format (Proto Enum) |
|---|---|
reservation.created | EVENT_TYPE_RESERVATION_CREATED |
reservation.dropped_off | EVENT_TYPE_DROPOFF |
reservation.picked_up | EVENT_TYPE_PICKUP |
reservation.cancelled | EVENT_TYPE_RESERVATION_CANCELLED |
reservation.pickup_failed | EVENT_TYPE_PICKUP_FAILED |
reservation.door_manually_opened | EVENT_TYPE_OPEN_DOOR_FULFILLED |
New Webhook Header
| Header | Description | Example |
|---|---|---|
X-Platform-Order-Id | Your original order ID from the reservation | order_12345 |
This header is now included in all webhook requests.
Updated X-Webhook-Event Header
The X-Webhook-Event header now uses proto enum values:
Before: X-Webhook-Event: reservation.dropped_off
After: X-Webhook-Event: EVENT_TYPE_DROPOFF
🔄 Migration Guide
Step 1: Update Event Type Parsing
// Before
switch (payload.event) {
case 'reservation.dropped_off':
handleDropoff(payload.data);
break;
case 'reservation.picked_up':
handlePickup(payload.data);
break;
}
// After
switch (payload.event_type) {
case 'EVENT_TYPE_DROPOFF':
handleDropoff(payload.drop_off_event);
break;
case 'EVENT_TYPE_PICKUP':
handlePickup(payload.pick_up_event);
break;
}
Step 2: Update Payload Field Access
// Before - envelope format with flat data
const orderId = payload.data.platform_order_id;
const cellDesc = payload.data.cell_description;
// After - flat format with nested event data
const orderId = payload.platform_order_id;
const cellDesc = payload.drop_off_event.cell.description;
Step 3: Update Idempotency Handling
// Before - using envelope id
const eventId = payload.id;
// After - using idempotency_key for deduplication
const idempotencyKey = payload.idempotency_key; // Same across retries
const eventId = payload.event_id; // Unique per delivery
📍 Affected Webhooks
All webhook event types are affected:
EVENT_TYPE_RESERVATION_CREATED- Reservation createdEVENT_TYPE_DROPOFF- Package dropped offEVENT_TYPE_PICKUP- Package picked upEVENT_TYPE_RESERVATION_CANCELLED- Reservation cancelledEVENT_TYPE_PICKUP_FAILED- Pickup attempt failedEVENT_TYPE_OPEN_DOOR_FULFILLED- Door open request completed
📚 Updated Documentation
The Webhook Integration documentation has been updated to reflect the new payload structure and includes:
- Complete payload examples for all event types
- Field reference tables
- Code examples for signature verification
- Idempotency handling guidance
Version 1.0.288 (2025-11-13)
✅ New Features
RequestMaintenance Endpoint
Added endpoint for platforms to report cell or locker issues requiring operations team attention.
- Endpoint:
POST /api/delivery/external/v1/maintenances - Purpose: Report cell/locker malfunctions or maintenance needs
- Features:
- Create maintenance tickets in the system
- Optional immediate cell blocking to prevent further reservations
- Integration with operations team workflow
- Use Cases:
- Report broken doors or mechanisms
- Flag cells with hardware issues
- Escalate repeated failure patterns
- Proactive maintenance requests
OpenDoor Endpoint (Out-of-Band)
Added asynchronous door opening endpoint for customer support and troubleshooting scenarios.
- Endpoint:
POST /api/delivery/external/v1/reservations/{reservation_id}/open-door - Purpose: Open locker door without changing reservation state
- Behavior:
- Async operation - request accepted immediately
- Webhook
EVENT_TYPE_OPEN_DOOR_FULFILLEDsent when completed - Use
request_id(fromX-Request-IDheader) to correlate API call with webhook
- Time Window Constraints:
- Cell allocation period (before drop-off)
- Drop-off grace period
- Awaiting pickup period (DROPPED_OFF state)
- Pickup grace period
- Extended window until cell is reallocated
- Parameters:
reason(optional): Explanation for opening (e.g., "Customer support request")platform_reference_id(optional): Your internal ticket/reference ID
- Error Handling:
- Immediate errors: Invalid reservation, auth failure, time window violation, device offline
- Deferred errors: Hardware failure, door mechanism issues (via webhook)
- Use Cases:
- Customer support assistance
- Door mechanism verification
- Emergency access situations
- Troubleshooting pickup issues
Cell Unique Identification
Added unique identifier for cells within machines.
- New Field:
cell_idinCellmessage - Purpose: Provides stable unique identifier for each cell
- Format: String, max length 128 characters
- Generated by: KF delivery platform
- Benefits:
- Consistent cell identification across API calls
- Better tracking and debugging
- Foundation for cell-specific analytics
🔄 Enhanced Webhook Events
New OpenDoor Fulfilled Event
Added webhook event for out-of-band door opening operations.
- Event Type:
EVENT_TYPE_OPEN_DOOR_FULFILLED(6) - Trigger: Sent when OpenDoor API request completes (success or failure)
- Payload (
OpenDoorFulfilledEvent):reservation_id: Reservation IDrequest_id: OriginalX-Request-IDfrom OpenDoor call (for correlation)cell: Cell that was opened (or attempted)success: Boolean indicating if door opened successfullyfulfilled_at: Timestamp when operation completederror_message: Optional error details ifsuccess = falsereason: Echoed reason from original requestplatform_reference_id: Echoed reference ID from original requestmachine: Machine information
- Use Cases:
- Confirm door opening for customer support
- Track success rate of manual interventions
- Alert on repeated failures
- Audit trail for support actions
📚 Improved Documentation
Enhanced Grace Period Documentation
Significantly enhanced documentation for DropOff and PickUp operations to clarify grace period behavior.
Key Clarifications:
- State transition timing:
DropOff: State changes toDROPPED_OFFimmediately when door opens (not when it closes)PickUp: State changes toPICKED_UPimmediately when door opens
- Grace period behavior:
- Grace period starts AFTER first successful door open
- Purpose: Allows re-opening the door during the period (not a delay)
- Both API and physical code methods share the same grace period timer
- Default: 120 seconds for both drop-off and pickup
- Subsequent calls: During grace period, can call DropOff/PickUp again to re-open door without changing state
Time Window Documentation
Added comprehensive documentation for OpenDoor API explaining valid time windows:
- Cell allocation period
- Drop-off grace period
- Awaiting pickup period
- Pickup grace period
- Extended window until reallocation
📍 Affected Endpoints
- New:
POST /api/delivery/external/v1/maintenances- Request maintenance - New:
POST /api/delivery/external/v1/reservations/{reservation_id}/open-door- Out-of-band door opening - Enhanced:
POST /api/delivery/external/v1/reservations/{reservation_id}/dropoffs- Improved documentation - Enhanced:
POST /api/delivery/external/v1/reservations/{reservation_id}/pickups- Improved documentation
📚 New Data Structures
- RequestMaintenanceRequest: Request structure for maintenance tickets
cell_idor machine-level issue- Issue description and severity
- Optional immediate cell blocking
- RequestMaintenanceResponse: Response with maintenance ticket information
- OpenDoorRequest: Request structure for out-of-band door opening
reservation_id(required)reason(optional): Explanation for openingplatform_reference_id(optional): Your internal reference
- OpenDoorResponse: Immediate response confirming request acceptance
- Webhook sent later when operation completes
- OpenDoorFulfilledEvent: Webhook event for completed door opening
- See webhook section above for full details
- Cell.cell_id: New string field (max 128 chars) for unique cell identification
Version 1.0.283 (2025-11-11)
✅ New Features
ListOngoingReservations Endpoint
Added comprehensive endpoint to retrieve all ongoing reservations with advanced filtering and pagination support.
- Endpoint:
GET /api/delivery/external/v1/reservations - Purpose: Query all ongoing reservations that are actively in use (not in terminal state)
- Ongoing States:
PENDING: Cell reserved, waiting for drop-offDROPPED_OFF: Package dropped off, waiting for pickupPICKED_UP: Package picked up but still within grace period (consumer can re-open door)
- Features:
- Pagination support with configurable page size (default: 100, max: 1000)
- Time-based filtering via
created_afterparameter (exclusive filter) - Results ordered by creation time (oldest first)
- Lightweight response optimized for list displays
- Total count of ongoing reservations
- Grace Period Logic: Reservations in
PICKED_UPstate remain in the list only while(current_time - picked_up_at) <= grace_period_pickup_seconds - Use Cases:
- Monitor active deliveries in progress
- Track packages waiting for consumer pickup
- Identify reservations needing attention
- Build real-time dashboards
- Support incremental sync workflows
Machine Occupancy Information
New real-time occupancy tracking for locker machines.
- New Field:
Machine.occupancy_information(type:OccupancyStatus) - Purpose: Provides real-time occupancy status including reserved cells
- Occupancy Levels:
LOW: ≤30% occupied - Machine is essentially emptyMEDIUM: 31-70% occupied - Machine is partially occupiedHIGH: >70% occupied - Machine is almost fullOVERLOADED: >95% occupied - Machine is overloaded
- Use Cases:
- Smart machine selection based on availability
- Capacity planning and monitoring
- Alert on overloaded machines
- Optimize delivery routing
Complete Cell Inventory
- New Field:
Machine.all_cells(repeatedCellInformation) - Purpose: Returns complete list of all cells configured for the machine
- Difference from
preferred_cells:preferred_cells: Non-exhaustive, KF-recommended cells blended by size. Only includes cells with status IDLE at the time of query (not reserved or occupied).all_cells: Complete inventory of all configured cells
- Use Cases:
- Understand full machine capacity
- Build custom cell selection logic
- Display complete cell availability
Request ID Tracing
New request ID fields for improved tracing and debugging.
- New Fields:
ReserveCellResponse.request_id: Stores theX-Request-IDheader from ReserveCell API callGetReservationResponse.request_id: Returns the stored request ID for tracing
- Purpose: End-to-end request tracing and debugging support
- Behavior: Automatically captured from
X-Request-IDheader if provided in reservation creation
🔄 Enhanced Webhook Events
New Pickup Failed Event
Added webhook event for failed pickup attempts.
- Event Type:
EVENT_TYPE_PICKUP_FAILED(5) - Trigger: Sent when a pickup attempt fails (door doesn't open)
- Payload (
PickUpFailedEvent):source_type: How user interacted (API, QR code, numeric code)request_id: Optional X-Request-ID header if from platform APIcell: Cell where pickup failedmachine: Machine informationerror_message: Details about the failure
- Use Cases:
- Alert on failed pickup attempts
- Track machine/door reliability
- Proactive customer support
- Detect potential fraud attempts
📚 Improved Documentation
Grace Period Behavior Clarification
Significantly enhanced documentation for grace period functionality in DropOff and PickUp operations.
Key Clarifications:
- Grace period purpose: Allows re-opening the door during the period, not a delay
- Drop-off grace period:
- Starts AFTER first successful door open
- Default: 120 seconds (configurable via
grace_period_dropoff_in_seconds) - Allows rider/driver to re-open if door accidentally closed
- State transition: State changes to
DROPPED_OFFonly when door closes (not when it opens)
- Pickup grace period:
- Starts AFTER first successful door open
- Default: 120 seconds (configurable via
grace_period_pickup_in_seconds) - Allows consumer to re-open if door accidentally closed
- State transition: State changes to
PICKED_UPimmediately when door opens successfully
- Shared timer: Both API and physical code methods share the same grace period
State Transition Documentation
Added comprehensive state transition diagrams and explanations highlighting asymmetric behavior:
Drop-off Flow (state changes on door close):
1. Call /dropoffs → Door opens (state: PENDING)
2. Driver places package
3. Door closes → State becomes DROPPED_OFF + webhook sent
└─ During grace period: Can call DropOff again (door re-opens, state stays DROPPED_OFF)
Pickup Flow (state changes on door open):
1. Call /pickups → Door opens + State becomes PICKED_UP + webhook sent
2. Consumer retrieves package
3. Door closes
└─ During grace period: Can call PickUp again (door re-opens, state stays PICKED_UP)
└─ After grace period: Reservation becomes terminal (excluded from ongoing list)
Why Asymmetric?
- Dropoff: Delayed state transition ensures the driver has successfully placed the package before marking as dropped off
- Pickup: Immediate state transition because opening the door means the consumer has accessed the package
🔧 Minor Improvements
- Documentation fix: Fixed typo "not exhausted" → "non-exhaustive" in machine cell descriptions
- Consistency: Updated "vot recommended" → "VoT recommended" in webhook messages
📍 Affected Endpoints
- New:
GET /api/delivery/external/v1/reservations- List ongoing reservations - Enhanced:
POST /api/delivery/external/v1/reservations- Now returnsrequest_idfield - Enhanced:
GET /api/delivery/external/v1/reservations/{reservation_id}- Now returnsrequest_idfield - Enhanced:
GET /api/delivery/external/v1/machines/{machine_id}andPOST /api/delivery/external/v1/machines/search- Now returnall_cellsandoccupancy_information
📚 New Data Structures
- ListOngoingReservationsRequest: Request with pagination and filtering
page_size(optional, default: 100, max: 1000)page_token(optional, for pagination)created_after(optional, unix timestamp for filtering)
- ListOngoingReservationsResponse: Response with reservation list and pagination
reservations(array ofReservationInfo)next_page_token(for pagination)total_count(approximate total)
- ReservationInfo: Lightweight reservation view
reservation_id,machine_id,platform_order_idstatus,created_at,dropped_off_at,picked_up_atcell(optional, only after drop-off)
- OccupancyStatus: Enum for machine occupancy levels
OCCUPANCY_STATUS_LOW(1): ≤30%OCCUPANCY_STATUS_MEDIUM(2): 31-70%OCCUPANCY_STATUS_HIGH(3): >70%OCCUPANCY_STATUS_OVERLOADED(4): >95%
- PickUpFailedEvent: Webhook event for failed pickups
source_type,request_id,cell,machine,error_message
Version 1.0.236 (2025-07-10)
✅ New Features
- GetReservation Endpoint: Added new endpoint to retrieve reservation details
- Endpoint:
GET /api/delivery/external/v1/reservations/{reservation_id} - Purpose: Allows platforms to query the current status and all information about a reservation
- Response: Returns comprehensive reservation details including status, timestamps, codes, and cell information
- Endpoint:
🔄 Changed
- Error Response Schema: Updated error response reference from
ErrorResponseto#/definitions/rpcStatus- Impact: Error responses now follow the standard gRPC status format
- Action Required: Update error handling to parse the new error format
📍 Affected Endpoints
- New:
GET /api/delivery/external/v1/reservations/{reservation_id} - Modified: All endpoints now return errors using the
rpcStatusschema
📚 New Data Structures
- GetReservationRequest: Request structure for retrieving reservation details
- GetReservationResponse: Comprehensive response with all reservation information including:
- Reservation status enum (PENDING, DROPPED_OFF, PICKED_UP, CANCELLED, ABANDONED)
- Machine details
- All timestamps (created, dropped off, picked up, cancelled, abandoned)
- Drop-off and pickup access codes with QR codes
- Assigned cell information (after drop-off)
Version 1.0.227 (2025-06-17)
🔄 Changed
- Internal improvements and optimizations
- No breaking changes or new features
Version 1.0.226 (2025-06-13)
🔄 Changed
- QR Code URLs Domain Update: Updated QR code URLs from
vendingontrack.comtokioskforce.com- Drop-off QR Code URLs: Now use
https://api.delivery.kioskforce.com/qrcode/{code}(production) orhttps://api-staging.delivery.kioskforce.com/qrcode/{code}(staging/dev) - Pickup QR Code URLs: Now use
https://api.delivery.kioskforce.com/qrcode/{code}(production) orhttps://api-staging.delivery.kioskforce.com/qrcode/{code}(staging/dev) - Impact: Existing QR codes will continue to work, but new reservations will receive updated URLs
- Action Required: Update any hardcoded domain references in your applications
- Drop-off QR Code URLs: Now use
📍 Affected Endpoints
POST /api/delivery/external/v1/reservations- ReserveCell response includes updated QR code URLs- Webhook events for reservation creation now include updated QR code URLs
Version 1.0.225 (2025-06-13)
✅ Stable Features
- Complete delivery locker reservation workflow
- Machine search with location and packaging filters
- Drop-off and pickup operations via API or physical codes
- Real-time webhook notifications for delivery events
- Support for both numeric codes and QR codes
🛠 Core Endpoints
- Echo:
POST /api/delivery/external/v1/echo - Search Machines:
POST /api/delivery/external/v1/machines/search - Get Machine:
GET /api/delivery/external/v1/machines/{machine_id} - Reserve Cell:
POST /api/delivery/external/v1/reservations - Drop Off:
POST /api/delivery/external/v1/reservations/{reservation_id}/dropoffs - Pick Up:
POST /api/delivery/external/v1/reservations/{reservation_id}/pickups - Cancel Reservation:
POST /api/delivery/external/v1/reservations/{reservation_id}/deletes - Abandon Pickup:
POST /api/delivery/external/v1/reservations/{reservation_id}/abandons
🔗 Webhook Events
EVENT_TYPE_RESERVATION_CREATED- When a cell is reservedEVENT_TYPE_DROPOFF- When a package is dropped offEVENT_TYPE_PICKUP- When a package is picked upEVENT_TYPE_RESERVATION_CANCELLED- When a reservation is cancelled
Migration Notes
Upgrading to v1.0.236
New GetReservation Endpoint
The new endpoint allows you to retrieve reservation details at any time:
GET /api/delivery/external/v1/reservations/{reservation_id}
Example response:
{
"reservation_id": "RES123456",
"machine_id": "MACH001",
"machine": { /* machine details */ },
"platform_order_id": "ORDER789",
"status": "RESERVATION_STATUS_DROPPED_OFF",
"created_at": "2025-07-10T10:00:00Z",
"drop_off_code": "1234",
"pickup_code": "5678",
"cell": { /* cell details if dropped off */ },
"dropped_off_at": "2025-07-10T10:30:00Z"
}
Error Response Format Change
Update your error handling to parse the new rpcStatus format:
Before (v1.0.227):
{
"error": "Invalid request",
"message": "Missing required field"
}
After (v1.0.236):
{
"code": 3,
"message": "Missing required field: reservation_id",
"details": []
}
Upgrading to v1.0.226
No breaking changes. The domain update is backward compatible:
- Existing QR codes from v1.0.225 will continue to work
- New reservations will receive updated QR code URLs with the new domain
- Webhook payloads will include the new QR code URLs for new events
- Update any hardcoded URLs in your application to use the new domain
Example Migration
Before (v1.0.225):
{
"drop_off_qrcode_url": "https://api.delivery.vendingontrack.com/qrcode/ABC123",
"pickup_code_qrcode_url": "https://api.delivery.vendingontrack.com/qrcode/DEF456"
}
After (v1.0.226):
{
"drop_off_qrcode_url": "https://api.delivery.kioskforce.com/qrcode/ABC123",
"pickup_code_qrcode_url": "https://api.delivery.kioskforce.com/qrcode/DEF456"
}
Staying Updated
- API Changes: Subscribe to our developer newsletter for API updates
- Documentation: This changelog is updated with each API release
- Support: Contact api-support@kioskforce.com for migration assistance
Version History
| Version | Release Date | Key Changes |
|---|---|---|
| 1.0.299 | 2026-01-23 | Breaking: Webhook payload structure overhaul - flat proto format, new event type values, X-Platform-Order-Id header |
| 1.0.288 | 2025-11-13 | RequestMaintenance and OpenDoor endpoints, cell_id field, OpenDoor fulfilled webhooks, enhanced grace period docs |
| 1.0.283 | 2025-11-11 | ListOngoingReservations endpoint, machine occupancy tracking, pickup failed webhooks, request ID tracing |
| 1.0.236 | 2025-07-10 | New GetReservation endpoint, updated error response schema |
| 1.0.227 | 2025-06-17 | Internal improvements |
| 1.0.226 | 2025-06-13 | QR code domain update to kioskforce.com |
| 1.0.225 | 2025-06-13 | Stable API release |