Access

Taps, presence and credentials — the gate rail. One `tap` write serves a school gate and a stadium door.

47 endpoints

GET /v3/band #
bearer driver_app beneficiary_app pass_app pass_web admin_web device credential

Query parameters

NameTypeConstraints
statusstring | nulloptionalin_stock assigned active suspended lost damaged retired
schoolstring | nulloptional
qstring | nulloptionalmax length 100
batchstring | nulloptionalmax length 50
colorstring | nulloptionalmax length 50

Response

Returns { "data": [BandRow] } with meta.next_cursor for the next page.

FieldTypeConstraints
idstring (uuid)required
serial_numberstringrequired
earth_codestring | nullrequired
batch_numberstring | nullrequired
colorstring | nullrequired
band_type_idstring | nullrequired
typestring | nullrequired
band_typeanyrequired
statusstringrequired
event_idstring | nullrequired
wearerstring | nullrequired
student_idstring | nullrequired
account_idstring | nullrequired
wallet_idstring | nullrequired
school_idstring | nullrequired
school_namestring | nullrequired
assigned_atstring | nullrequired
expires_atstring | nullrequired
created_atstring (date-time)required
POST /v3/band #
bearer driver_app beneficiary_app admin_web pass_web access.band_manage device credential

Request body

FieldTypeConstraints
serial_numberstringrequiredmax length 64
earth_codestring | nulloptionalmax length 32
batch_numberstring | nulloptionalmax length 64
colorstring | nulloptionalmax length 32
band_type_idstring | nulloptional
school_idstring (uuid)optional
expires_atstring | nulloptional

Response

Returns { "data": BandWrite }.

FieldTypeConstraints
idstring (uuid)required
serial_numberstringrequired
earth_codestring | nullrequired
batch_numberstring | nullrequired
colorstring | nullrequired
band_type_idstring | nullrequired
statusstringrequired
student_idstring | nullrequired
account_idstring | nullrequired
wallet_idstring | nullrequired
assigned_atstring | nullrequired
expires_atstring | nullrequired
event_idstring | nullrequired
GET /v3/band-type #
bearer driver_app beneficiary_app pass_app pass_web admin_web device credential

Query parameters

NameTypeConstraints
schoolstring | nulloptional

Response

Returns { "data": [BandType] } with meta.next_cursor for the next page.

FieldTypeConstraints
idstring (uuid)required
namestringrequired
POST /v3/band/assign #
bearer driver_app beneficiary_app pass_app admin_web access.band_manage device credential

Request body

FieldTypeConstraints
serial_numberstringrequiredmax length 64
student_idstring | nulloptional
account_idstring | nulloptional
wallet_idstring | nulloptional

Response

Returns { "data": BandWrite }.

FieldTypeConstraints
idstring (uuid)required
serial_numberstringrequired
earth_codestring | nullrequired
batch_numberstring | nullrequired
colorstring | nullrequired
band_type_idstring | nullrequired
statusstringrequired
student_idstring | nullrequired
account_idstring | nullrequired
wallet_idstring | nullrequired
assigned_atstring | nullrequired
expires_atstring | nullrequired
event_idstring | nullrequired
POST /v3/band/bulk #
bearer driver_app beneficiary_app admin_web pass_web access.band_manage device credential

A factory shipment, in one call.

Answers per serial rather than with a count, because the operator is holding the spreadsheet the list came from and needs to know WHICH rows to look at. Re-sending the same list is safe: every serial comes back duplicate, nothing 409s, and the shipment is not half-registered.

Request body

FieldTypeConstraints
serial_numbersstring | null[]requiredmin items 1 · max items 2000
batch_numberstring | nulloptionalmax length 64
colorstring | nulloptionalmax length 32
band_type_idstring | nulloptional
school_idstring (uuid)optional
event_idstring | nulloptional
expires_atstring | nulloptional

Response

Returns { "data": BandBulkIntake }.

FieldTypeConstraints
registeredintegerrequired
duplicateintegerrequired
invalidintegerrequired
resultsobject[]required
GET /v3/band/{serial} #
bearer driver_app beneficiary_app pass_app pass_web admin_web device credential

Path parameters

NameTypeNotes
serialstring

Response

Returns { "data": BandDetail }.

FieldTypeConstraints
idstring (uuid)required
serial_numberstringrequired
earth_codestring | nullrequired
batch_numberstring | nullrequired
colorstring | nullrequired
band_type_idstring | nullrequired
statusstringrequired
student_idstring | nullrequired
account_idstring | nullrequired
wallet_idstring | nullrequired
assigned_atstring | nullrequired
expires_atstring | nullrequired
tagsobject[]required
weareranyrequired
walletanyrequired
POST /v3/band/{serial}/replace #
bearer driver_app beneficiary_app pass_app admin_web access.band_manage device credential

a dead wristband swapped for a live one (Cloud9 3).

The wearer and their wallet come off the band being replaced, never off the request: naming them would let a caller point the balance at somebody else. One transaction, so a failure leaves the guest with the working band they already had rather than two dead ones and a balance they cannot spend.

Path parameters

NameTypeNotes
serialstring

Request body

FieldTypeConstraints
serial_numberstringrequiredmax length 64
reasonstringrequiredlost damaged

Response

Returns { "data": BandWrite }.

FieldTypeConstraints
idstring (uuid)required
serial_numberstringrequired
earth_codestring | nullrequired
batch_numberstring | nullrequired
colorstring | nullrequired
band_type_idstring | nullrequired
statusstringrequired
student_idstring | nullrequired
account_idstring | nullrequired
wallet_idstring | nullrequired
assigned_atstring | nullrequired
expires_atstring | nullrequired
event_idstring | nullrequired
POST /v3/band/{serial}/status #
bearer driver_app beneficiary_app pass_app admin_web access.band_manage device credential

Path parameters

NameTypeNotes
serialstring

Request body

FieldTypeConstraints
statusstringrequiredin_stock assigned active suspended lost damaged retired

Response

Returns { "data": BandWrite }.

FieldTypeConstraints
idstring (uuid)required
serial_numberstringrequired
earth_codestring | nullrequired
batch_numberstring | nullrequired
colorstring | nullrequired
band_type_idstring | nullrequired
statusstringrequired
student_idstring | nullrequired
account_idstring | nullrequired
wallet_idstring | nullrequired
assigned_atstring | nullrequired
expires_atstring | nullrequired
event_idstring | nullrequired
POST /v3/device/heartbeat #
bearer driver_app beneficiary_app pass_app device credential

Request body

FieldTypeConstraints
serial_numberstringrequiredmax length 64
battery_pctinteger | nulloptionalmin 0 · max 100
signal_strengthinteger | nulloptionalmin 0 · max 10
firmwarestring | nulloptionalmax length 64
data_used_bytesinteger | nulloptionalmin 0
sim_presentboolean | nulloptional
recorded_atstring (date-time)required

Response

Returns { "data": HeartbeatAck }.

FieldTypeConstraints
okbooleanrequired
presencestringrequiredonline low_battery
next_heartbeat_secondsintegerrequired
POST /v3/portal/band-type #
bearer admin_web access.band_manage device credential

Request body

FieldTypeConstraints
namestringrequiredmax length 80
school_idstring (uuid)optional

Response

Returns { "data": BandType }.

FieldTypeConstraints
idstring (uuid)required
namestringrequired
DELETE /v3/portal/band-type/{id} #
bearer admin_web access.band_manage device credential

Path parameters

NameTypeNotes
idstring

Response

Returns { "data": Deleted }.

FieldTypeConstraints
deletedbooleanrequired
PATCH /v3/portal/band-type/{id} #
bearer admin_web access.band_manage device credential

Path parameters

NameTypeNotes
idstring

Request body

FieldTypeConstraints
namestringrequiredmax length 80

Response

Returns { "data": BandType }.

FieldTypeConstraints
idstring (uuid)required
namestringrequired
PATCH /v3/portal/band/{id} #
bearer admin_web access.band_manage device credential

Path parameters

NameTypeNotes
idstring

Request body

FieldTypeConstraints
band_type_idstring | nulloptional
school_idstring (uuid)optional
statusstringoptionalin_stock assigned active suspended lost damaged retired

Response

Returns { "data": BandEdited }.

FieldTypeConstraints
idstring (uuid)required
serial_numberstringrequired
earth_codestring | nullrequired
batch_numberstring | nullrequired
colorstring | nullrequired
band_type_idstring | nullrequired
statusstringrequired
student_idstring | nullrequired
account_idstring | nullrequired
wallet_idstring | nullrequired
assigned_atstring | nullrequired
expires_atstring | nullrequired
school_idstring | nullrequired
school_namestring | nullrequired
POST /v3/portal/band/{serial}/school #
bearer admin_web access.band_manage device credential

Path parameters

NameTypeNotes
serialstring

Request body

FieldTypeConstraints
school_idstring (uuid)required

Response

Returns { "data": BandAssignedToSchool }.

FieldTypeConstraints
idstring (uuid)required
serial_numberstringrequired
earth_codestring | nullrequired
batch_numberstring | nullrequired
colorstring | nullrequired
band_type_idstring | nullrequired
statusstringrequired
student_idstring | nullrequired
account_idstring | nullrequired
wallet_idstring | nullrequired
assigned_atstring | nullrequired
expires_atstring | nullrequired
tagsobject[]required
weareranyrequired
walletanyrequired
school_idstring (uuid)required
school_namestringrequired
GET /v3/portal/device #
bearer admin_web device credential

Query parameters

NameTypeConstraints
statusstring | nulloptionalprovisioned approved maintenance retired blocked
kindstring | nulloptionalscanner onboard_unit pos gate
zone_idstring | nulloptional
qstring | nulloptionalmax length 120
schoolstring | nulloptional
batch_numberstring | nulloptionalmax length 64
cursorstring | nulloptionalmax length 200
per_pageinteger | nulloptionalmin 1 · max 500

Response

Returns { "data": [WebDevice] } with meta.next_cursor for the next page.

FieldTypeConstraints
idstring (uuid)required
namestring | nullrequired
serial_numberstringrequired
batch_numberstring | nullrequired
kindstringrequired
statusstringrequired
zoneanyrequired
schoolanyrequired
imeistring | nullrequired
sim_msisdnstring | nullrequired
sim_presentboolean | nullrequired
battery_pctinteger | nullrequired
signal_strengthinteger | nullrequired
firmwarestring | nullrequired
data_used_bytesinteger | nullrequired
presencestringrequired
last_seen_atstring | nullrequired
row_versionintegerrequired
POST /v3/portal/device #
bearer admin_web access.device_manage device credential

Request body

FieldTypeConstraints
namestringrequiredmax length 120
serial_numberstringrequiredmax length 64
kindstring | nulloptionalscanner onboard_unit pos gate mobile browser
zone_idstring | nulloptional
school_idstring | nulloptional
imeistring | nulloptionalmax length 32
sim_msisdnstring | nulloptionalmax length 20
firmwarestring | nulloptionalmax length 64
batch_numberstring | nulloptionalmax length 80

Response

Returns { "data": WebDevice }.

FieldTypeConstraints
idstring (uuid)required
namestring | nullrequired
serial_numberstringrequired
batch_numberstring | nullrequired
kindstringrequired
statusstringrequired
zoneanyrequired
schoolanyrequired
imeistring | nullrequired
sim_msisdnstring | nullrequired
sim_presentboolean | nullrequired
battery_pctinteger | nullrequired
signal_strengthinteger | nullrequired
firmwarestring | nullrequired
data_used_bytesinteger | nullrequired
presencestringrequired
last_seen_atstring | nullrequired
row_versionintegerrequired
GET /v3/portal/device/batch-numbers #
bearer admin_web device credential

Response

An array of string.

PATCH /v3/portal/device/bulk/school #
bearer admin_web access.device_manage device credential

Request body

FieldTypeConstraints
device_idsstring (uuid)[]requiredmin items 1 · max items 500
school_idstring (uuid)required

Response

Returns { "data": [WebDevice] } with meta.next_cursor for the next page.

FieldTypeConstraints
idstring (uuid)required
namestring | nullrequired
serial_numberstringrequired
batch_numberstring | nullrequired
kindstringrequired
statusstringrequired
zoneanyrequired
schoolanyrequired
imeistring | nullrequired
sim_msisdnstring | nullrequired
sim_presentboolean | nullrequired
battery_pctinteger | nullrequired
signal_strengthinteger | nullrequired
firmwarestring | nullrequired
data_used_bytesinteger | nullrequired
presencestringrequired
last_seen_atstring | nullrequired
row_versionintegerrequired
GET /v3/portal/device/stats #
bearer admin_web device credential

Response

Returns { "data": WebDeviceStats }.

FieldTypeConstraints
total_wearablesintegerrequired
wearables_assignedintegerrequired
total_scannersintegerrequired
scanners_assignedintegerrequired
PATCH /v3/portal/device/{id} #
bearer admin_web access.device_manage device credential

Path parameters

NameTypeNotes
idstring

Request body

FieldTypeConstraints
update_maskstring[]requiredmin items 1 · max items 7
expected_row_versionintegerrequiredmin 1
namestring | nulloptionalmax length 120
kindstring | nulloptionalscanner onboard_unit pos gate mobile browser
statusstring | nulloptionalprovisioned approved maintenance retired blocked
zone_idstring | nulloptional
imeistring | nulloptionalmax length 32
sim_msisdnstring | nulloptionalmax length 20
firmwarestring | nulloptionalmax length 64

Response

Returns { "data": WebDevice }.

FieldTypeConstraints
idstring (uuid)required
namestring | nullrequired
serial_numberstringrequired
batch_numberstring | nullrequired
kindstringrequired
statusstringrequired
zoneanyrequired
schoolanyrequired
imeistring | nullrequired
sim_msisdnstring | nullrequired
sim_presentboolean | nullrequired
battery_pctinteger | nullrequired
signal_strengthinteger | nullrequired
firmwarestring | nullrequired
data_used_bytesinteger | nullrequired
presencestringrequired
last_seen_atstring | nullrequired
row_versionintegerrequired
POST /v3/portal/device/{id}/airtime #
bearer admin_web money.adjust device idempotency credential

Path parameters

NameTypeNotes
idstring

Request body

FieldTypeConstraints
amount_minorintegerrequiredmin 1 · max 100000000
currencystringrequiredmin length 3 · max length 3

Response

Returns { "data": … }; this endpoint's payload is not yet pinned to a named shape.

GET /v3/portal/device/{id}/history #
bearer admin_web device credential

Path parameters

NameTypeNotes
idstring

Query parameters

NameTypeConstraints
fromstringrequired
tostringrequired
cursorstring | nulloptionalmax length 200
per_pageinteger | nulloptionalmin 1 · max 500

Response

Returns { "data": [DeviceHistoryEntry] }.

FieldTypeConstraints
idstring (uuid)required
kindstringrequired
changesobjectrequired
actor_user_idstring | nullrequired
atstring (date-time)required
PATCH /v3/portal/device/{id}/school #
bearer admin_web access.device_manage device credential

Path parameters

NameTypeNotes
idstring

Request body

FieldTypeConstraints
school_idstring (uuid)required

Response

Returns { "data": WebDevice }.

FieldTypeConstraints
idstring (uuid)required
namestring | nullrequired
serial_numberstringrequired
batch_numberstring | nullrequired
kindstringrequired
statusstringrequired
zoneanyrequired
schoolanyrequired
imeistring | nullrequired
sim_msisdnstring | nullrequired
sim_presentboolean | nullrequired
battery_pctinteger | nullrequired
signal_strengthinteger | nullrequired
firmwarestring | nullrequired
data_used_bytesinteger | nullrequired
presencestringrequired
last_seen_atstring | nullrequired
row_versionintegerrequired
POST /v3/portal/pickup/confirm #
bearer admin_web access.tap_manual device credential

Request body

FieldTypeConstraints
codestringrequiredmin length 4 · max length 12
student_idstring (uuid)required
zone_idstring | nulloptional
outcomestring | nulloptionalreleased declined

Response

Returns { "data": Ack }.

FieldTypeConstraints
okbooleanrequired
POST /v3/portal/pickup/validate #
bearer admin_web access.tap_manual device credential

Request body

FieldTypeConstraints
codestringrequiredmin length 4 · max length 12

Response

Returns { "data": PickupValidation }.

FieldTypeConstraints
studentobjectrequired
student.idstring (uuid)required
student.namestringrequired
student.gradestring | nullrequired
student.photoanyrequired
guardianobjectrequired
guardian.account_idstring (uuid)required
guardian.namestringrequired
guardian.phonestring | nullrequired
guardian.relationshipstring | nullrequired
GET /v3/portal/zone #
bearer admin_web device credential

Query parameters

NameTypeConstraints
kindstring | nulloptionalschool gate bus canteen library office event other +2 more
exclude_kindstring | nulloptionalschool gate bus canteen library office event other +2 more
qstring | nulloptionalmax length 120
cursorstring | nulloptionalmax length 200
per_pageinteger | nulloptionalmin 1 · max 500

Response

Returns { "data": [WebZone] } with meta.next_cursor for the next page.

FieldTypeConstraints
idstring (uuid)required
parent_zone_idstring | nullrequired
namestringrequired
kindstringrequired
statusstringrequired
descriptionstring | nullrequired
metadataobjectrequired
centroidanyrequired
geofence_radius_minteger | nullrequired
occupancyintegerrequired
assigneesobject[]required
chargesobject[]required
vehicleanyrequired
row_versionintegerrequired
POST /v3/portal/zone #
bearer admin_web settings.manage device credential

Request body

FieldTypeConstraints
namestringrequiredmax length 120
kindstring | nulloptionalschool gate bus canteen library office cocurricular other
descriptionstring | nulloptionalmax length 300
parent_zone_idstring | nulloptional
centroid_latnumber | nulloptionalmin -90 · max 90
centroid_lngnumber | nulloptionalmin -180 · max 180
geofence_radius_minteger | nulloptionalmin 10 · max 10000
metadataarray | nulloptionalmax items 20

Response

Returns { "data": WebZone }.

FieldTypeConstraints
idstring (uuid)required
parent_zone_idstring | nullrequired
namestringrequired
kindstringrequired
statusstringrequired
descriptionstring | nullrequired
metadataobjectrequired
centroidanyrequired
geofence_radius_minteger | nullrequired
occupancyintegerrequired
assigneesobject[]required
chargesobject[]required
vehicleanyrequired
row_versionintegerrequired
PATCH /v3/portal/zone/{id} #
bearer admin_web settings.manage device credential

Path parameters

NameTypeNotes
idstring

Request body

FieldTypeConstraints
update_maskstring[]requiredmin items 1 · max items 9
expected_row_versionintegerrequiredmin 1
namestring | nulloptionalmax length 120
kindstring | nulloptionalschool gate bus canteen library office event other +2 more
statusstring | nulloptionalactive suspended archived
descriptionstring | nulloptionalmax length 300
parent_zone_idstring | nulloptional
centroid_latnumber | nulloptionalmin -90 · max 90
centroid_lngnumber | nulloptionalmin -180 · max 180
geofence_radius_minteger | nulloptionalmin 10 · max 10000
metadataarray | nulloptionalmax items 20

Response

Returns { "data": WebZone }.

FieldTypeConstraints
idstring (uuid)required
parent_zone_idstring | nullrequired
namestringrequired
kindstringrequired
statusstringrequired
descriptionstring | nullrequired
metadataobjectrequired
centroidanyrequired
geofence_radius_minteger | nullrequired
occupancyintegerrequired
assigneesobject[]required
chargesobject[]required
vehicleanyrequired
row_versionintegerrequired
PUT /v3/portal/zone/{id}/access-mode #
bearer admin_web settings.manage device credential

the explicit open|rostered flip (admin judgment; reach.md §3.4).

Path parameters

NameTypeNotes
idstring

Request body

FieldTypeConstraints
access_modestringrequiredopen rostered

Response

Returns { "data": AccessModeSet }.

FieldTypeConstraints
zone_idstring (uuid)required
access_modestringrequired
GET /v3/portal/zone/{id}/profile #
bearer admin_web device credential

The location profile (SP-8, terra-api §11.7): meal periods + the priced menu as ONE document-shaped read over TYPED rows (0090). The projections and writes live ON the models (databases are classes) — this controller only orchestrates.

Path parameters

NameTypeNotes
idstring

Response

Returns { "data": ZoneProfile }.

FieldTypeConstraints
periodsobject[]required
menu_itemsobject[]required
PUT /v3/portal/zone/{id}/profile #
bearer admin_web settings.manage device credential

PUT replaces each PROVIDED collection wholesale — the config card saves the whole form; an omitted collection is untouched.

Path parameters

NameTypeNotes
idstring

Request body

FieldTypeConstraints
periodsobject[]optionalmax items 12
menu_itemsobject[]optionalmax items 200

Response

Returns { "data": ZoneProfile }.

FieldTypeConstraints
periodsobject[]required
menu_itemsobject[]required
GET /v3/portal/zone/{id}/roster #
bearer admin_web device credential

the zone's members (provenance visible) + rules + mode.

Path parameters

NameTypeNotes
idstring

Response

Returns { "data": WebRoster }.

FieldTypeConstraints
zone_idstring (uuid)required
access_modestringrequired
membersobject[]required
rulesobject[]required
POST /v3/portal/zone/{id}/roster/member #
bearer admin_web settings.manage device credential

a hand-picked member (via='manual').

Path parameters

NameTypeNotes
idstring

Request body

FieldTypeConstraints
student_idstring (uuid)optional
account_idstring (uuid)optional

Response

Returns { "data": Written }.

FieldTypeConstraints
idstring (uuid)required
DELETE /v3/portal/zone/{id}/roster/member/{memberId} #
bearer admin_web settings.manage device credential

manual members only (rule rows belong to their rule).

Path parameters

NameTypeNotes
idstring
memberIdstring

Response

Returns { "data": Deleted }.

FieldTypeConstraints
deletedbooleanrequired
POST /v3/portal/zone/{id}/roster/rule #
bearer admin_web settings.manage device credential

label-based auto-enrollment; the projector materializes.

Path parameters

NameTypeNotes
idstring

Request body

FieldTypeConstraints
tag_idsstring (uuid)[]requiredmin items 1 · max items 8

Response

Returns { "data": … }; this endpoint's payload is not yet pinned to a named shape.

DELETE /v3/portal/zone/{id}/roster/rule/{ruleId} #
bearer admin_web settings.manage device credential

its members cascade; the projector re-covers survivors.

Path parameters

NameTypeNotes
idstring
ruleIdstring

Response

Returns { "data": Deleted }.

FieldTypeConstraints
deletedbooleanrequired
GET /v3/portal/zone/{id}/service-log #
bearer admin_web device credential

Path parameters

NameTypeNotes
idstring

Query parameters

NameTypeConstraints
kindstring | nulloptionalfuel maintenance
fromstring | nulloptional
tostring | nulloptional
cursorstring | nulloptionalmax length 200
per_pageinteger | nulloptionalmin 1 · max 500

Response

Returns { "data": [ServiceLog] } with meta.next_cursor for the next page.

FieldTypeConstraints
idstring (uuid)required
kindstringrequired
occurred_onstring | nullrequired
amount_minorinteger | nullrequired
currencystring | nullrequired
quantity_litersnumber | nullrequired
odometer_kminteger | nullrequired
descriptionstring | nullrequired
POST /v3/portal/zone/{id}/service-log #
bearer admin_web transport.plan device credential

Path parameters

NameTypeNotes
idstring

Request body

FieldTypeConstraints
kindstringrequiredfuel maintenance
occurred_onstringrequired
amount_minorinteger | nulloptionalmin 0 · max -9223372036854775808
currencystring | nulloptionalmin length 3 · max length 3
quantity_litersnumber | nulloptionalmin 0 · max 99999
odometer_kminteger | nulloptionalmin 0
descriptionstring | nulloptionalmax length 500
metadataarray | nulloptionalmax items 20

Response

Returns { "data": ServiceLog }.

FieldTypeConstraints
idstring (uuid)required
kindstringrequired
occurred_onstring | nullrequired
amount_minorinteger | nullrequired
currencystring | nullrequired
quantity_litersnumber | nullrequired
odometer_kminteger | nullrequired
descriptionstring | nullrequired
DELETE /v3/portal/zone/{id}/service-log/{logId} #
bearer admin_web transport.plan device credential

Path parameters

NameTypeNotes
idstring
logIdstring

Response

Returns { "data": Deleted }.

FieldTypeConstraints
deletedbooleanrequired
PATCH /v3/portal/zone/{id}/service-log/{logId} #
bearer admin_web transport.plan device credential

Path parameters

NameTypeNotes
idstring
logIdstring

Request body

FieldTypeConstraints
update_maskstring[]requiredmin items 1 · max items 8
kindstring | nulloptionalfuel maintenance
occurred_onstring | nulloptional
amount_minorinteger | nulloptionalmin 0 · max -9223372036854775808
currencystring | nulloptionalmin length 3 · max length 3
quantity_litersnumber | nulloptionalmin 0 · max 99999
odometer_kminteger | nulloptionalmin 0
descriptionstring | nulloptionalmax length 500
metadataarray | nulloptionalmax items 20

Response

Returns { "data": ServiceLog }.

FieldTypeConstraints
idstring (uuid)required
kindstringrequired
occurred_onstring | nullrequired
amount_minorinteger | nullrequired
currencystring | nullrequired
quantity_litersnumber | nullrequired
odometer_kminteger | nullrequired
descriptionstring | nullrequired
PUT /v3/portal/zone/{id}/vehicle #
bearer admin_web settings.manage device credential

The real fleet record (0115) — capacity/fuel_type/fuel_consumption live on `vehicles`, not zones.metadata. Required the first time (a new bus), partial-edit-friendly after that (WebVehicleService).

Path parameters

NameTypeNotes
idstring

Request body

FieldTypeConstraints
capacityinteger | nulloptionalmin 1 · max 999
fuel_typestring | nulloptionalpetrol diesel electric hybrid
fuel_consumption_km_per_lnumber | nulloptionalmin 3 · max 12

Response

Returns { "data": VehicleFields }.

FieldTypeConstraints
zone_idstring (uuid)required
capacityinteger | nullrequired
fuel_typestring | nullrequired
fuel_consumption_km_per_lnumber | nullrequired
GET /v3/presence #
bearer beneficiary_app parent_app device credential

Query parameters

NameTypeConstraints
studentsstringrequiredmax length 8000

Response

Returns { "data": [PresenceEntry] } with meta.next_cursor for the next page.

FieldTypeConstraints
student_idstringrequired
statestringrequiredpresent away none
pathobject[]optional
sincestring | nulloptional
last_zoneobjectoptional
last_zone.idstringrequired
last_zone.namestring | nulloptional
last_seenstring | nulloptional
POST /v3/student/{id}/pickup-code #
bearer beneficiary_app parent_app admin_web device credential

Path parameters

NameTypeNotes
idstring

Request body

FieldTypeConstraints
account_idstring | nulloptional

Response

Returns { "data": PickupCodeMinted }.

FieldTypeConstraints
codestringrequired
expires_atstring (date-time)required
POST /v3/tap #
bearer driver_app beneficiary_app pass_app device credential

Request body

FieldTypeConstraints
client_event_idstring (uuid)required
zone_idstring (uuid)required
device_idstring | nulloptional
band_serialstring | nulloptionalmax length 64
student_idstring | nulloptional
directionstringrequiredcheck_in check_out
methodstringrequirednfc manual qr
occurred_atstring (date-time)required
pickup_codestring | nulloptionalmax length 10

Response

Returns { "data": TapVerdict }.

FieldTypeConstraints
resultstringrequiredallowed denied noop
reasonstringoptional
detailstringoptional
holderstringoptional
admitsstring[]optional
chargeobjectoptional
charge.transaction_idstring (uuid)required
charge.amountobjectrequired
charge.balance_afterobjectrequired
POST /v3/tap/batch #
bearer driver_app beneficiary_app pass_app device credential gzip

Offline outbox drain: PER-ITEM results — one poisoned item never sinks the batch (§7.3). The cap is `terra.batch.max_items`, the same number bootstrap advertises to the apps. Items process sequentially (each tap is its own transaction), so a max-size reconnect drain is bounded by a TIME BUDGET instead of item count: past the budget the loop stops and the response carries only the processed prefix — an omitted item has no result, which the app's drain already reads as "keep & retry next cycle". Worst-case latency is capped; no tap is ever dropped.

Items are applied in occurred_at ORDER, not the order the array happened to arrive in (0136). Presence is a fold over a sequence, so applying a check-out before the check-in it follows leaves the holder inside forever — and the array order is whatever the handset's outbox produced after its own retries, which is not a guarantee anybody made. Sorting is one usort and removes the whole class.

The time budget then truncates the LATEST taps rather than an arbitrary suffix, which is the right half to re-drain: the oldest facts land first and the newest come back next cycle.

The REPLY still comes back in the order the caller sent, though. Applying in time order is ours to decide; re-ordering somebody's array under them is not, and a client lining results up by position would silently read the wrong verdict against the wrong tap. Results are collected against each item's original index and sorted back before they go out.

Headers

HeaderNotes
Content-EncodingoptionalOptional request-body compression; compressed cap 1 MB, decompressed cap 10 MB.

Request body

FieldTypeConstraints
tapsarrayrequiredmin items 1 · max items 500

Response

Returns { "data": TapBatch }.

FieldTypeConstraints
resultsTapBatchItem[]required
POST /v3/tap/{event}/undo #
bearer driver_app beneficiary_app pass_app admin_web access.undo device credential

reverse a mis-tap by its access-event id. Idempotent by construction — a replay returns the same compensating facts.

Path parameters

NameTypeNotes
eventstring

Response

Returns { "data": … }; this endpoint's payload is not yet pinned to a named shape.

GET /v3/zone/{id}/occupancy #
bearer driver_app beneficiary_app pass_app pass_web admin_web device credential

Path parameters

NameTypeNotes
idstring

Response

Returns { "data": Occupancy }.

FieldTypeConstraints
zone_idstring (uuid)required
namestringrequired
containerobjectrequired
container.idstring (uuid)required
container.namestringrequired
open_sessionsintegerrequired
as_ofstringrequired