Skip to content
Support the creatorSupport

HTTP contract

Part Value
Method http.method: POST (default) or PUT
URL http.url. No URL (null or '') = record only, never upload.
Content-Type application/json
Accept application/json
Other headers http.headers, then Authorization: Bearer <accessToken> when credentials are stored (it wins over a configured Authorization).
Timeout http.timeoutSec (default 30 s, 5–120)

Each record is the location record JSON, or the rendered http.locationTemplate.

Config Body
batch: true (default) { ...params, [rootProperty ?? 'locations']: [r1, r2, …] }, up to maxBatchSize records
batch: false { ...params, [rootProperty ?? 'location']: r }, one request per record
batch: false, rootProperty: '.' { ...params, ...r }
batch: true, rootProperty: '.' Treated as 'locations' (so a remote config that turns batching on is never refused).

If a params key has the same name as the root property, the records win. Records go oldest first.

  • A record is inserted and uploadIntervalSec is 0, or that many seconds have passed since the last attempt.
  • Connectivity comes back.
  • sync() or setAuthorization() is called (both skip backoff and the 15-minute auth pause).
  • The 60-second watchdog finds records waiting and the next-attempt time has passed.

One upload at a time. A run keeps sending until the queue is empty or a request fails. Uploads continue after stop() until the queue is empty.

Response Records Then
2xx Deleted. Backoff resets. If the body is JSON with a long_ping object: reset: true clears the server’s stored values, then config is merged into them when remoteConfig is true and configchange fires; stop: true stops tracking and fires enabledchange.
401 / 403 Kept. With a stored refreshUrl: POST refreshPayload with refreshHeaders, read access_token | accessToken and optional refresh_token | refreshToken, store them, retry the batch once. Otherwise, or if the refresh fails: authorizationRequired = true, authorization event { status, error }, uploads pause until setAuthorization() or 15 minutes pass. Location keeps running.
413 Kept. Retried immediately with half the batch (minimum 1).
408, 429, 5xx, network error, timeout Kept. Backoff min(900, 10 × 2ⁿ) s with ±20 % jitter. A Retry-After header in seconds wins (iOS also accepts the HTTP-date form).
Other 4xx attempts + 1; records reaching 3 attempts are deleted (logged as dropped). The current run ends; records retry on the next trigger at normal pace.

Every attempt emits an http event { status, ok, count, responseText } (status 0 = network error, responseText = the first 2 KB) and writes a log line. While a request is in flight the device holds a partial wake lock (Android, 60 s timeout) or a background task (iOS).

{ "long_ping": { "reset": false, "config": { "movingIntervalSec": 5 }, "stop": false } }
Key Effect
long_ping.reset true clears every value the server has set; runs before config in the same reply.
long_ping.config Partial config, kept as the server’s own layer on top of the app’s config, so it survives configure() and restarts. Ignored (not stored) when remoteConfig is false. A config that fails validation is rejected whole and logged.
long_ping.stop true stops tracking. Queued records still upload.

Only read from 2xx responses. See Remote config & remote stop.

POST <refreshUrl>
Content-Type: application/json
<refreshHeaders>
{"refresh_token": "<stored refresh token>"}

The body is refreshPayload with {{refreshToken}} replaced; the default is shown. The reply must be JSON with access_token (or accessToken) and may include refresh_token (or refreshToken).