Skip to content

Credit travel time to a day

Credits the employee's configured travel time allowance to a date.

Two successful outcomes, both on the happy path:

  • 201 — the minutes were placed and paid; the body carries the time point.
  • 202 — the day had no room the system would use, so the request was filed as a PENDING time point correction for a validator to place by hand. Nothing has been credited yet and the allowance is untouched.

Placement. A day's payable total is bounded by the shape of its rows: each row runs until the next one starts, so a block laid over payable time only relabels minutes already counted. Only a placement that replaces UNPAYABLE time, or extends past the day's outer edge, actually pays. Three are tried in order, and the first that fits the WHOLE allowance wins:

  • start_of_day — ends exactly where the day's first PAYABLE status begins. Unpayable rows at the start of a day (a midnight rollover row, an auto-stop row, an early break) are room rather than an obstacle.
  • end_of_day — appended after the day's last CLOSED row, then closed again by the employee's own last unpayable status, or the configured stop status.
  • mid_day — the tail of an unpayable stretch, preferring one that work resumes after. This is what covers a day the employee is still clocked in on.

An empty day is anchored at the PBX's configured empty day time (06:00 by default) and closed by the configured stop status. Repeat requests on the same day chain backwards from the earlier credit, producing one contiguous block.

Guarantees. A credit is exactly the configured minutes or it is not written (partial credits no longer exist); it never crosses another row's boundary, so at most one existing row is touched — its end pulled back to the credit's start, with the old value kept in that row's meta_data.travel_time_trimmed; live (open) rows are never touched; nothing is written into the future. After the write the day's payable seconds are re-measured and compared against the value before it — anything other than exactly the allowance is rolled back and returned as 202.

The credit is recorded as an accepted time point correction, so it appears in the employee's correction history and remains correctable afterwards. No acceptance email is sent.

The caller may only credit their own travel time: the request is rejected with 403 when the authenticated user has no access to the tenant or the employee record is not their own, and with 404 when the employee cannot be found.

HTTP: bearerAuth

User bearer token. Default authentication for customer-facing endpoints. Obtain a token by calling POST /login with your credentials, then send it on every subsequent request as Authorization: Bearer <token>. The token inherits the permissions and PBX scope of the authenticated user.

HTTP Authorization Scheme
bearer
Bearer format
Bearer <token>
pbx_id path · string · uuid *
UUID of the PBX tenant.
employee_id path · string · uuid *
UUID of the employee to credit.
accept header · string
example: application/json

Request body

Request schema
datestring · date
The date to credit, `Y-m-d`. Defaults to today. Must not be in the future, and must not be older than the PBX's configured `travel_time.max_past_days` window (31 days by default).
example: 2026-05-11
commentstring | null
Optional note stored on the credit. Defaults to a generated "Travel time requested" comment.
length: 0–500
example: Client site visit

Responses

The travel time credit was applied.
Response schema
message*string
example: Travel time has been added.
data*object
timepoint_id*string · uuid
UUID of the time point created for the credit.
example: 550e8400-e29b-41d4-a716-446655440012
correction_id*string · uuid
UUID of the accepted correction row behind the credit.
example: 550e8400-e29b-41d4-a716-446655440013
placement*string
Which placement was used, so a client can explain a timestamp that is not first thing in the morning.
enum: start_of_day end_of_day mid_day empty_day
example: start_of_day
status_id*string · uuid
UUID of the PBX travel time status.
example: 550e8400-e29b-41d4-a716-446655440011
start_time*string
Start of the credited block, `Y-m-d H:i:s`.
example: 2026-05-11 07:30:00
end_timestring | null
End of the credited block, `Y-m-d H:i:s`.
example: 2026-05-11 08:00:00
minutesinteger | null · int32
Minutes credited. Always equal to the configured allowance — a placement that cannot pay it in full is refused rather than shortened. Null only for the pathological case of a time point written without an end.
example: 30
commentstring | null
The comment stored on the credit.
example: Client site visit
meta*object
used_today*integer · int32
example: 1
remaining_today*integer · int32
example: 0
pending_today*integer · int32
Requests for today waiting for HR. Nothing credited for these.
example: 0
The day had no room the system would use, so the request was filed as a pending time point correction for a validator. NOTHING has been credited: there is no time point, the allowance is untouched, and `pending_today` counts the waiting request. A second request for the same date is refused with `already_pending` until this one is settled.
Response schema
message*string
example: Please contact HR as your day has no room available for adjusting this timepoint. Your request has been sent to them for approval.
code*string
enum: pending_hr_review
example: pending_hr_review
data*object
correction_id*string · uuid
UUID of the pending correction a validator will settle.
example: 550e8400-e29b-41d4-a716-446655440013
status_id*string · uuid
UUID of the PBX travel time status.
example: 550e8400-e29b-41d4-a716-446655440011
requested_timestring | null
The placement the system wanted, `Y-m-d H:i:s` — thirty minutes before the day's first payable status, or the PBX's empty day anchor when that falls off the day.
example: 2026-05-11 06:00:00
commentstring | null
The comment the employee sent with the request.
example: Client site visit
meta*object
used_today*integer · int32
example: 0
remaining_today*integer · int32
example: 1
pending_today*integer · int32
example: 1
Authorization Token Missing. This error is returned when the authorization token is missing.
Response schema
errorstring
Error message
example: Authorization Token is missing
The authenticated user has no access to the requested tenant, or the requested employee record does not belong to the authenticated user.
Response schema
No response body.
Data Not Found. This error is returned when the requested data is not found.
Response schema
messagearray<string>
[]string
Either the `date` or `comment` field failed validation (standard validation error body), or a travel time guard refused the request. Guard refusals carry a stable machine readable `code` alongside the translated `message`: | code | meaning | |---|---| | `not_allowed` | Travel time is not enabled for this employee. | | `employee_user_missing` | The employee is not linked to a user account. | | `status_not_configured` | No status is marked as travel time for the PBX. | | `status_ambiguous` | More than one status is marked as travel time. | | `stop_status_not_configured` | The day is empty and no stop status is configured. | | `stop_status_same_as_travel` | The stop status is misconfigured to equal the travel status. | | `minutes_not_configured` | The configured duration is zero or negative. | | `date_in_future` | The requested date is in the future. | | `date_locked` | The requested date is older than the allowed window. | | `no_contract` | The employee has no active contract on that date. | | `absence_day` | The date is covered by an approved absence. | | `limit_reached` | The per-date allowance is already used up. | | `already_pending` | A request for this date is already waiting for HR. |
Response schema
oneOf
message*string
example: The travel time limit for this date has already been reached.
code*string
example: limit_reached
message*string
example: The given data was invalid.
errors*object
Free-form object
post https://cockpit.voxbi.com/api/v1/{pbx_id}/user/{employee_id}/travel-time
Base URL
Request sample
curl -X POST 'https://cockpit.voxbi.com/api/v1/{pbx_id}/user/{employee_id}/travel-time' \
  -H 'Authorization: Bearer YOUR_TOKEN'
const response = await fetch('https://cockpit.voxbi.com/api/v1/{pbx_id}/user/{employee_id}/travel-time', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${YOUR_TOKEN}`,
  },
});

const data = await response.json();
console.log(data);
import requests

response = requests.post('https://cockpit.voxbi.com/api/v1/{pbx_id}/user/{employee_id}/travel-time',
    headers={'Authorization': f'Bearer {YOUR_TOKEN}'}
)
response.raise_for_status()
data = response.json()
print(data)
<?php
$context = stream_context_create([
    'http' => [
        'method'  => 'POST',
        'header'  => "Content-Type: application/json\r\nAuthorization: Bearer YOUR_TOKEN",
    ],
]);

$response = file_get_contents('https://cockpit.voxbi.com/api/v1/{pbx_id}/user/{employee_id}/travel-time', false, $context);
$data = json_decode($response, true);
print_r($data);
Sample request
No request example provided.
No example for this status.
No example for this status.
{}
"error": "Authorization Token is missing"
}
Cache-Control string
example: private, must-revalidate
Connection string
example: keep-alive
Content-Type string
example: application/json
Vary string
example: Origin
X-RateLimit-Limit integer
Max requests allowed in the current rate-limit window.
example: 60
X-RateLimit-Remaining integer
Requests remaining in the current rate-limit window.
example: 57
No example for this status.
{}
"message": []
"Data not found"
]
}
Cache-Control string
example: private, must-revalidate
Connection string
example: keep-alive
Content-Type string
example: application/json
Vary string
example: Origin
X-RateLimit-Limit integer
Max requests allowed in the current rate-limit window.
example: 60
X-RateLimit-Remaining integer
Requests remaining in the current rate-limit window.
example: 57
No example for this status.