Developer API/Overview
Developer API

The fleet & telematics data plane for your integration.

A public REST API for reading and acting on fleets, vehicles, drivers, journeys, live positions, video and device commands. Built for third-party developers.

REST · OpenAPI 3.1 · OAuth2 client-credentials · Cursor pagination · snake_case JSON · CloudEvents webhooks
Base URL
https://developer.haloniq.com
REST OpenAPI 3.1 OAuth2 CloudEvents 1.0
19
OAuth2 scopes
10
Resource groups
3.1
OpenAPI document
1.0
CloudEvents webhooks
Getting started

From credentials to first call in four steps.

Every endpoint requires an OAuth2 client-credentials bearer token carrying the scopes it needs. There is no user login: this is a server-to-server integration.

1Obtain client credentials

Get a client_id and client_secret for your integration from your Haloniq administrator. Credentials are scoped to your organization and its descendant tenants.

2Request a token

Exchange your credentials at the identity token endpoint using the client_credentials grant. Ask only for the scopes you need.

get a token
curl -X POST https://identity.haloniq.com/connect/token \
  -d grant_type=client_credentials \
  -d client_id=YOUR_CLIENT_ID \
  -d client_secret=YOUR_CLIENT_SECRET \
  -d scope="thirdparty.api.fleets_read thirdparty.api.vehicles_read"
3Call an endpoint

Send the returned access_token as a Bearer header. Responses are snake_case JSON; list endpoints are cursor-paginated.

call the API
curl https://developer.haloniq.com/v1/fleets \
  -H "Authorization: Bearer $ACCESS_TOKEN"
4Explore interactively

Browse every resource, schema and example in the Scalar reference, or pull the machine-readable OpenAPI 3.1 document to generate a client SDK.

Authentication & scopes

One scope per resource and action.

Requests are authorized by OAuth2 scopes. Read and write are granted separately, and device commands are split so wake-up can be allowed without reboot. A missing scope returns 403.

All scopes are prefixed thirdparty.api. Request only what your integration uses.
ScopeGrants
Read
thirdparty.api.organizations_readRead organizations across your tenant hierarchy.
thirdparty.api.fleets_readRead fleets and their membership.
thirdparty.api.vehicles_readRead vehicles and vehicle telemetry.
thirdparty.api.drivers_readRead driver records.
thirdparty.api.devices_readRead devices, device telemetry and media items.
thirdparty.api.events_readSearch telematics events over a date window.
thirdparty.api.journeys_readQuery completed journeys for a vehicle, fleet or device.
thirdparty.api.live_positions_readRead real-time vehicle positions.
thirdparty.api.webhooks_readRead webhook subscription configuration.
Write
thirdparty.api.fleets_writeCreate and update fleets.
thirdparty.api.vehicles_writeCreate and update vehicles.
thirdparty.api.drivers_writeUpdate driver records.
thirdparty.api.devices_writeAssign and unassign devices.
thirdparty.api.video_requests_writeRequest video and media uploads from devices.
thirdparty.api.live_streams_writeStart live video streams from device cameras.
thirdparty.api.playback_sessions_writeStart video playback sessions.
thirdparty.api.webhooks_writeCreate and manage webhook subscriptions.
Device commands
thirdparty.api.device_commands_rebootSend a reboot command to a device.
thirdparty.api.device_commands_wake_upSend a wake-up command to a device.
Capabilities

What the API exposes.

A versioned surface over the platform's fleet and telematics data plane, all under /v1.

Fleets & Vehicles

Read and manage your fleet structure and vehicle records, including per-vehicle telemetry.

Drivers

Read and update driver records across your organization.

Journeys

Query completed journeys over a date window for a vehicle, fleet or device.

Live Positions

Poll real-time vehicle positions across the fleets you can see.

Events

Search telematics events with narrowing filters and a date window.

Media & Video

List device media with signed download URLs and request new video uploads.

Streaming

Start live streams and playback sessions from device cameras.

Devices & Commands

List devices, read telemetry, assign to vehicles, and reboot or wake them remotely.

Organizations

Traverse your tenant's organization hierarchy and descendants.

Webhooks

Subscribe to CloudEvents 1.0 messages the platform POSTs to your endpoints.

Webhooks

Push, not poll: CloudEvents delivered to your endpoint.

Subscribe once and the platform POSTs a application/cloudevents+json envelope to your endpoint whenever something happens on your fleet. Every message follows the CloudEvents 1.0 specification, so the envelope is identical across all topic types. Only the data payload changes with the event type.

The CloudEvents envelope

Wire content type application/cloudevents+json, the structured envelope wrapping every delivery.
FieldTypeNotes
idstringRequired. Producer idempotency key (event / alarm id, or hardwareId:utc). De-duplicate on this.
sourceuri-referenceRequired. Origin of the event, e.g. /brigade/events, /brigade/livetrack.
typestringRequired. One of the five topic types below. Discriminates the data schema.
specversionstringRequired. Constant "1.0".
timedate-timeDevice wire time (not processing time).
datacontenttypestringMedia type of data; defaults to application/json.
subjectstringDevice / hardware id.
dataschemauriSchema URI for the data payload.
dataobjectThe type-specific payload, one of the five records below.

Topic types & payloads

Five outbound topic types. The CloudEvents type discriminates the schema. Payload property names are camelCase, unlike the snake_case REST API.

CloudEvents typeFires onPayload highlights
live.gpsEach live GPS fix (topic live_gps)hardwareId, latitude, longitude, heading, speed, utc, invalidGps
journey.closedA journey completes (topic journeys)journeyId, hardwareId, startUtc / endUtc, start & end lat-long, distanceMeters, durationSeconds
alarm.triggeredA device raises an alarm (topic alarms)id, hardwareId, triggerOn, alarmKey, locations[], speedPoints[], headingPoints[]
event.genericA telematics event (topic events)eventId, hardwareId, triggerUtc, eventTypes[], eventCategories[], isAccident, locations[], address, vehicleId
media.readyRequested media is ready (topic media)mediaId, hardwareId, fileName, mimeType, channel, downloadUrl (time-limited SAS)

Delivery transports

The delivery plane fans each event out to the subscriber's chosen transport. Through the Developer API today you subscribe over HTTPS callback; the Event Hub and Kafka transports are platform capabilities provisioned out-of-band (roadmap for self-serve).

TransportVia Developer APIBest for
HttpCallbackYes, the default and only self-serve transport. POSTs the CloudEvents envelope to your HTTPS URL.Any subscriber with an HTTPS endpoint.
AzureEventHubPlatform / roadmap, provisioned out-of-band.High-volume Azure-native streaming into your own Event Hub.
KafkaPlatform / roadmap, provisioned out-of-band (SASL/SSL).Streaming into your own Kafka cluster.

Delivery headers & retries

Headers on each HTTPS delivery. Return any 2xx to acknowledge; a non-2xx or a timeout is retried with back-off (a response Retry-After header is honored).
HeaderMeaning
X-Webhook-KeyYour organization's shared auth key, sent verbatim so you can authenticate the sender. Declared in the OpenAPI webhooks doc.
X-Delivery-Attempt1-based attempt number; a value >1 means a retry after a prior non-2xx / timeout. De-duplicate against the envelope id. Declared in the OpenAPI webhooks doc.
Idempotency-KeyStable per (event, destination) delivery id. Use it for exactly-once handling.
traceparentW3C trace context, when present.

Optional per-destination custom headers exist at the delivery-worker level but are not settable through the Developer API today.

Authentication is a shared key, not a signature. Each delivery carries your X-Webhook-Key verbatim so you can authenticate the sender. There is no HMAC and no payload signing today, so verify the shared key on receipt and rotate it via the regenerate-auth-key endpoint.

Subscribing with the webhook-config API

Manage your subscription under /v1/organizations/{organizationId}/webhook-config. Reads require thirdparty.api.webhooks_read; every mutation requires thirdparty.api.webhooks_write. Optimistic concurrency uses ETag / If-Match (stale → 412); secrets are never returned by GET (only an auth_key_hint).

Method & pathScopePurpose
GET /webhook-configwebhooks_readRead the config; 404 if none. Secrets redacted to auth_key_hint.
PUT /webhook-configwebhooks_writeCreate-or-replace the whole config. If-Match required once it exists.
PATCH /webhook-configwebhooks_writeEnable / disable delivery.
DELETE /webhook-configwebhooks_writeDelete the config. 204.
POST /webhook-config/regenerate-auth-keywebhooks_writeRotate the auth key; the raw key is returned exactly once.
PUT /webhook-config/topics/{topicType}webhooks_writeUpsert one topic (max 25). {topicType} = events | alarms | media | live_gps | journeys.
DELETE /webhook-config/topics/{topicType}webhooks_writeRemove one topic. The last remaining topic cannot be removed (409).
subscribe to a topic
# register an HTTPS callback for closed journeys
curl -X PUT https://developer.haloniq.com/v1/organizations/$ORG_ID/webhook-config/topics/journeys \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"type":"journeys","is_enabled":true,"delivery":{"url":"https://your-app.example.com/hooks/haloniq"}}'

Callback URLs must be absolute HTTPS, ≤2048 chars, and not loopback, link-local or private ranges (an SSRF guard blocks localhost, 127.0.0.0/8, 10/8, 172.16/12, 192.168/16, 169.254/16, ::1). Violations return 422 webhook.ssrf_blocked.

SDK Generator

Generate a typed client from the OpenAPI 3.1 document.

The API publishes a machine-readable OpenAPI 3.1 document at /openapi/v1.json. Point a generator at it and get a fully typed client with no hand-written HTTP. Two generators are supported: Microsoft Kiota (the partner-SDK generator, multi-language) and NSwag (a dependency-light single-file C# client).

Microsoft Kiota: multi-language typed client

Kiota emits a request-builder tree (client.V1.Fleets[id].GetAsync()) and generates for C#, Java, Go, Python, TypeScript, PHP and Ruby from the same spec. OpenAPI 3.1 is detected natively, so no flag is needed.

generate with Kiota
# freeze the OpenAPI 3.1 document as the generation input
curl -fsSL https://developer.haloniq.com/openapi/v1.json -o v1.json

# one-time: install the generator
dotnet tool install --global Microsoft.OpenApi.Kiota

# generate the typed C# client (multi-file, request-builder tree)
kiota generate \
  -l CSharp \
  -d v1.json \
  -o ./sdk/kiota \
  -n Haloniq.DeveloperApi.Client \
  -c DeveloperApiClient \
  --clean-output

NSwag: single-file C# client

NSwag emits one .cs file with flat methods (client.GetFleetAsync(id)). Pin a 3.1-capable 14.x build, because 13.x mishandles the 3.1 type-arrays.

generate with NSwag
# one-time: install a 3.1-capable build (pin 14.7.1)
dotnet tool install --global NSwag.ConsoleCore --version 14.7.1

# emit a single-file C# client
nswag openapi2csclient \
  /input:v1.json \
  /classname:DeveloperApiClient \
  /namespace:Haloniq.DeveloperApi.Client \
  /output:DeveloperApiClient.cs

Which to choose

DimensionKiotaNSwag
Output shapeMany files: models plus a request-builder treeOne .cs file
Call styleFluent: client.V1.Fleets[id].GetAsync()Flat: client.GetFleetAsync(id)
LanguagesC# / Java / Go / Python / TypeScript / PHP / RubyC# / TypeScript
SerializationSystem.Text.Json (pluggable)Newtonsoft.Json by default (System.Text.Json opt-in)
DependenciesMicrosoft.Kiota.BundleJust Newtonsoft.Json (none with System.Text.Json)
OpenAPI 3.1Native, no flagNeeds a 14.x build

Rule of thumb: ship a partner SDK with Kiota when you need more than one target language: one spec generates C#, Java, Python, Go and TypeScript from the same tool. Reach for NSwag when you want a dependency-light, drop-in single C# file for a quick smoke call, a console harness, or an independent cross-check of the contract. Both parse the 3.1.1 document; verify by running dotnet build on the generated project and confirming 0 errors.

Reference output

A reference C# SDK, the frozen spec and the regeneration scripts are kept in this repository under .workspace/developer-api-handoff/sdk/, in the recommended layout:

.workspace/developer-api-handoff/sdk/
sdk/
├── openapi/v1.json                 # frozen OpenAPI 3.1 doc = generation input
├── kiota/                          # Kiota multi-file client (Haloniq.DeveloperApi.Client)
│   ├── kiota-lock.json             # enables `kiota update` re-generation
│   └── Haloniq.DeveloperApi.Client.csproj
└── nswag/
    └── DeveloperApiClient.cs       # single-file NSwag client

Re-generate after a spec change with kiota update (it reads kiota-lock.json) or by re-running the NSwag command above.