Skip to content

HTTP API

The ingestion API is how push-mode integrations (the Minecraft plugin, the SDK, or your own code) send data to Tickr. It’s four endpoints under https://api.tickr.gg/v1.

Authentication

Every request authenticates with a server key (tickr_sk_…), created in the dashboard under Server → Settings → API key, sent as a bearer token:

Authorization: Bearer tickr_sk_xxxxxxxxxxxxxxxx

Keys are scoped to a single server. Revoke and rotate them from the dashboard at any time.

Rate limits & batching

  • 600 requests per minute per key. Exceeding it returns 429 with a Rate limit exceeded error, so back off and retry.
  • Session and event payloads are batches of 1 to 500 items. Prefer fewer, larger requests over many small ones.
  • Timestamps (ts) are epoch milliseconds from the source machine; values before 2020 or more than 5 minutes in the future are rejected.

POST /v1/ingest/sessions

Records player join/leave activity (world switches are sent as a leave + join pair sharing the sessionId).

{
  "batch": [
    {
      "playerId": "069a79f4-44e9-4726-a5be-fca90e38aaf5",
      "username": "Steve",
      "type": "join",
      "sessionId": "9b2f6dc4-3a1e-4c8e-9f6a-2d1e0b7c5a44",
      "world": "bedwars-lobby",
      "ts": 1750000000000
    }
  ]
}
FieldTypeNotes
playerIdstring (1-64)Stable pseudonymous id (UUID, SteamID, etc). Required.
usernamestring (≤64)Optional display name.
type"join" | "leave"Required.
sessionIdUUIDRequired; pairs the join with its leave.
worldstring (≤120)Optional world / backend server name.
tsnumberEpoch ms. Required.

POST /v1/ingest/events

Custom events with optional category, numeric value and free-form properties. Requires a paid plan (see license check).

{
  "batch": [
    {
      "name": "bedwars_win",
      "category": "minigame",
      "playerId": "069a79f4-44e9-4726-a5be-fca90e38aaf5",
      "value": 1,
      "properties": { "map": "lighthouse" },
      "idempotencyKey": "f3c9a1b2-7d4e-4f08-a6b5-1c2d3e4f5a6b",
      "ts": 1750000000000
    }
  ]
}
FieldTypeNotes
namestringRequired; ^[a-z0-9_:-]{1,64}$ (lowercase snake/kebab).
categorystring (≤64)Optional grouping such as minigame, economy, …
playerIdstring (≤64)Optional; omit for server-level events.
valuenumberOptional numeric value (amounts, durations).
propertiesobjectOptional free-form JSON properties.
idempotencyKeystring (8-64)Required; see below.
tsnumberEpoch ms. Required.

Idempotency

Network retries must never double-count an event. Each event carries a client-generated idempotencyKey (a random UUID is fine); if Tickr has already accepted an event with the same key for this server, the duplicate is silently skipped. This makes the safe retry strategy trivial: resend the whole batch on any failure. Already-ingested items are deduplicated, missing items are stored. The SDK and plugin auto-generate keys for you.

POST /v1/ingest/heartbeat

A small, unbatched liveness ping. Send one every ~30 seconds:

{ "tps": 19.97, "cleanShutdown": false }
FieldTypeNotes
tpsnumber (0-1000)Optional current tick rate.
cleanShutdownbooleanOptional; send true as the final heartbeat of a graceful stop.

Heartbeats power crash detection: if a server goes silent without a cleanShutdown: true heartbeat, the downtime is classified as a crash and shows up in post-mortems; with it, it’s a clean restart.

GET /v1/ingest/license

Returns the entitlements of the plan behind this server key:

{ "premium": true, "plan": "pro" }

Use it to gate premium-only features (like custom events) client-side instead of sending payloads that will be rejected. The plugin polls this every 10 minutes so plan upgrades apply without a restart.

Errors

StatusMeaning
401Missing or invalid server key.
422Validation failed; response body lists the offending fields.
429Rate limit exceeded (600 req/min/key); back off and retry.
5xxTransient server error; retry with exponential backoff.