Skip to main content

HTTP REST API Reference

TinyMQ exposes a language-agnostic HTTP API. Any client capable of making HTTP requests — curl, Python requests, PHP, Node.js, Rust — can interact with the broker without any special libraries.

Base URL: http://localhost:7800 (or your PORT setting)


Endpoints Summary

MethodEndpointDescription
POST/publish/{topic}Publish a message
GET/consume/{topic}Consume / long-poll for messages
POST/ack/{topic}/{id}Acknowledge a message
POST/requeueRe-queue a message (increment retry count)
POST/api/queues/redriveRedrive dead-lettered messages from DLQ
POST/webhook/{topic}Register a push webhook
POST/api/topicsCreate a topic manually
POST/api/groupsCreate a Consumer Group
GET/api/groupsList Consumer Groups for a topic
GET/api/cluster/statusGet cluster diagnostics
POST/api/drainMark node as draining (graceful maintenance)
GET/api/statsGet broker statistics
GET/metricsGet Prometheus metrics
GET/healthzHealthcheck endpoint
GET/dashboardInteractive web dashboard

Dashboard/JSON API (Alternative):

MethodEndpointDescription
GET/api/queuesList all queues
POST/api/queues/publishPublish via JSON body
POST/api/queues/consumeConsume via JSON body
GET/api/queues/peekPeek at queue contents
DELETE/api/queues/purgePurge all messages from a queue
DELETE/api/queues/deleteDelete queue entirely
GET/api/queues/webhooksList webhooks for a queue

POST /publish/{topic}

Publish a message to a topic. The topic is created automatically on first publish.

Query Parameters

ParameterTypeDescription
ttldurationTime-To-Live. Message is dropped if not consumed before expiry. Examples: 30s, 5m, 1h
delaydurationDelivery delay. Message is hidden until this duration passes. Examples: 10s, 1m
broadcastboolIf true, delivers to all waiting consumers simultaneously (ephemeral — not persisted)
prioritystringEnqueue with priority: high, normal, or low. (Default: normal)
idempotencystringSet to auto to use payload SHA256 as idempotency key

Headers

HeaderDescription
Idempotency-KeyA unique string (e.g. uuid). If a duplicate key is sent within 5 minutes, it is silently accepted but discarded.
X-MQ-*Any custom header starting with X-MQ- is stored with the message.

Request Body

Raw bytes (JSON, plain text, binary). Maximum size: 2MB.

curl -X POST "http://localhost:7800/publish/orders.eu?ttl=10m&priority=high" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: txn-12345" \
-d '{"user_id": 42, "item": "laptop"}'

GET /consume/{topic}

Consume one or more messages from a topic. Supports long-polling.

Query Parameters

ParameterTypeDefaultDescription
timeoutduration0sHold connection open this long if queue is empty (long-polling). E.g., 5s, 10s
limitint1Number of messages to extract in one call
auto_ackboolfalseIf true, messages are ACK'd immediately upon delivery
groupstring(empty)Consumer Group name for Pub/Sub. E.g. billing
peekboolfalseIf true, reads messages without consuming/ACKing them
filter_keystring(empty)Smart Routing: Only return messages with this exact JSON key
filter_valstring(empty)Smart Routing: Value to match against filter_key
# Consume with 10s long-poll, batch of 5, auto-acknowledged, as group "billing"
curl "http://localhost:7800/consume/orders.eu?timeout=10s&limit=5&auto_ack=true&group=billing"

Response

Single message (limit=1, default):

{
"id": "a1b2c3d4-7c89-4b1a-9f5e-123456789abc",
"topic": "orders.eu",
"payload": "eyJ1c2VyX2lkIjogNDIsICJpdGVtIjogImxhcHRvcCJ9",
"payload_text": "{\"user_id\": 42, \"item\": \"laptop\"}",
"timestamp": "2026-06-18T10:00:00Z",
"retry_count": 0
}
Payload Encoding

payload is returned as Base64-encoded bytes. If the bytes form valid UTF-8 text, payload_text is also populated for convenience.


POST /ack/{topic}/{id}

Acknowledge a message, removing it from RAM and writing an ACK record to the WAL. Required when auto_ack=false.

curl -X POST http://localhost:7800/ack/orders.eu/a1b2c3d4-7c89-4b1a-9f5e-123456789abc

POST /requeue

Re-queue a message, incrementing its retry_count. After 3 attempts, the broker routes it to {topic}.dlq. The request body must be a full message JSON object.


POST /api/queues/redrive?queue={topic}

Redrives all dead-lettered messages from {topic}.dlq back to the main {topic} queue. The retry counters are reset, and the messages are removed from the DLQ.

curl -X POST http://localhost:7800/api/queues/redrive?queue=orders.eu

POST /webhook/{topic}

Register a URL to receive messages from a topic via HTTP POST (push/webhook pattern).

curl -X POST http://localhost:7800/webhook/orders.eu \
-H "Content-Type: application/json" \
-d '{"url": "https://api.my-service.com/hook", "secret": "my-hmac-secret"}'

If secret is provided, outbound POSTs will include an X-TinyMQ-Signature header containing an HMAC-SHA256 signature of the payload.


POST /api/topics

Pre-initialize a topic. Useful for Consumer Group wiring or setting Retain rules.

curl -X POST http://localhost:7800/api/topics \
-H "Content-Type: application/json" \
-d '{"name": "analytics.events", "policy": "reject", "retain": "24h"}'
  • policy: Overflow policy (reject or drop-oldest) when max limit (100k) is hit.
  • retain: Auto-apply this TTL to all messages published to this topic.

GET /metrics

Returns standard Prometheus metrics for observability.

curl http://localhost:7800/metrics

GET /healthz

Healthcheck endpoint used for Docker/Kubernetes probes.

  • 200 OK — broker is healthy and ready
  • 503 Service Unavailable — returned mid-election (no recognized leader yet). Kubernetes readiness probes will stop routing traffic automatically.
curl http://localhost:7800/healthz

Response in standalone mode:

{ "status": "ok", "version": "3.1.0", "uptime_seconds": 3600 }

Response in cluster mode:

{
"status": "ok",
"version": "3.1.0",
"uptime_seconds": 3600,
"cluster_role": "leader",
"cluster_term": 3
}

cluster_role can be: "leader", "follower", or "candidate".

Response during election:

{ "status": "electing" }

POST /api/drain

Marks the node as draining immediately. All subsequent requests will return 503 Service Unavailable. Intended for controlled maintenance restarts — load balancers and Kubernetes readiness probes will automatically stop routing traffic.

curl -X POST http://localhost:7800/api/drain

Response:

{ "status": "draining", "in_flight_requests": 3 }
Drain is permanent for the process lifetime

There is no un-drain API. To recover, restart the process. Use tmq cluster drain <node-url> from the CLI to avoid accidentally targeting the wrong node.


POST /api/groups & GET /api/groups

Manage Consumer Groups explicitly. Groups allow multiple independent services to consume identical messages without stealing from each other.

Create a Group:

curl -X POST http://localhost:7800/api/groups \
-H "Content-Type: application/json" \
-d '{"topic": "orders.eu", "group": "billing"}'

List Groups:

curl http://localhost:7800/api/groups?topic=orders.eu

GET /api/cluster/status

Returns diagnostic information about the node's participation in the TinyMQ High Availability cluster, including its role, current term, the leader's address, and peer health status.

curl http://localhost:7800/api/cluster/status

Dashboard JSON APIs (/api/queues/*)

These endpoints accept JSON bodies instead of URL path parameters. They are heavily used by the embedded dashboard.

  • GET /api/queues: Returns a list of all active queues.
  • POST /api/queues/publish: JSON body with {"queue": "topic", "payload": "...", "ttl": "...", "delay": "...", "priority": "...", "broadcast": false}
  • POST /api/queues/consume: JSON body with {"queue": "topic"}
  • GET /api/queues/peek?queue=orders.eu: Returns an array of up to 10 messages without removing them.
  • POST /api/queues/redrive?queue=orders.eu: Redrives messages from DLQ to main topic.
  • DELETE /api/queues/purge?queue=orders.eu: Empties the queue.
  • DELETE /api/queues/delete?queue=orders.eu: Deletes the queue and its WAL file.
  • GET /api/queues/webhooks?queue=orders.eu: Returns a list of webhook URLs for the queue.

Error Reference

HTTP StatusMeaningTypical Cause
400 Bad RequestMalformed requestMissing topic, empty body, invalid duration
403 ForbiddenAccess DeniedTINYMQ_MAX_TOPICS limit reached
404 Not FoundResource not foundEmpty queue (on consume), unknown message ID
409 ConflictAlready existsCreating a topic that already exists
413 Request Entity Too LargePayload too bigPayload exceeds 2MB
429 Too Many RequestsBackpressureQueue RAM limit (100k messages) reached