Poll-Based Delivery
Poll-based delivery lets consumers pull events from Mittr instead of receiving HTTP pushes. This is useful when your consumer can’t expose a public URL, runs behind a firewall, or needs to control the rate of processing.
How it works
Section titled “How it works”- Create an endpoint with
deliveryModeset topoll - Your consumer calls
GET /api/v1/pollto fetch pending events - Process the events
- Acknowledge successful events with
POST /api/v1/poll/ack - Unacknowledged events are redelivered after the visibility timeout
Create a poll endpoint
Section titled “Create a poll endpoint”curl -X POST https://app.mittr.io/api/v1/endpoints \ -H "X-API-Key: mtr_your_key" \ -H "Content-Type: application/json" \ -d '{ "url": "poll://my-consumer", "deliveryMode": "poll", "eventTypes": ["order.*"] }'The url field is a label for poll endpoints — no HTTP requests are made to it.
Fetch events
Section titled “Fetch events”Long-poll for pending events:
curl "https://app.mittr.io/api/v1/poll?endpoint_id=ep_uuid&limit=50&timeout=30" \ -H "X-API-Key: mtr_your_key"Parameters
Section titled “Parameters”| Parameter | Type | Default | Description |
|---|---|---|---|
endpoint_id | string | required | The poll endpoint ID |
limit | integer | 10 | Max events to return (1-100) |
timeout | integer | 30 | Long-poll timeout in seconds (1-60) |
Response
Section titled “Response”{ "events": [ { "id": "evt_abc", "eventType": "order.created", "payload": { "orderId": "ord_123", "amount": 9900 }, "headers": { "X-Source": "shop-prod" }, "createdAt": "2026-04-14T10:30:00Z" } ], "count": 1}The event id is used as the acknowledgement key.
Long-polling behavior
Section titled “Long-polling behavior”- If events are available, they are returned immediately
- If no events are available, the request blocks until events arrive or
timeoutelapses - An empty response with
"events": []means no events arrived during the timeout
Acknowledge events
Section titled “Acknowledge events”After processing, acknowledge events to remove them from the queue:
curl -X POST https://app.mittr.io/api/v1/poll/ack \ -H "X-API-Key: mtr_your_key" \ -H "Content-Type: application/json" \ -d '{ "endpoint_id": "ep_uuid", "event_ids": ["evt_xyz", "evt_abc"] }'Acknowledged events are marked as delivered. Unacknowledged events become visible again after the visibility timeout and are redelivered on the next poll.
Example consumer
Section titled “Example consumer”Node.js
Section titled “Node.js”async function pollLoop(endpointId, apiKey) { const baseUrl = 'https://app.mittr.io/api/v1';
while (true) { try { // Long-poll for events (blocks up to 30 seconds) const res = await fetch( `${baseUrl}/poll?endpoint_id=${endpointId}&limit=50&timeout=30`, { headers: { 'X-API-Key': apiKey } } ); const { events } = await res.json();
if (events.length === 0) continue;
// Process events const acked = []; for (const event of events) { try { await processEvent(event); acked.push(event.id); } catch (err) { console.error(`Failed to process ${event.id}:`, err); // Don't acknowledge — will be redelivered } }
// Acknowledge processed events if (acked.length > 0) { await fetch(`${baseUrl}/poll/ack`, { method: 'POST', headers: { 'X-API-Key': apiKey, 'Content-Type': 'application/json' }, body: JSON.stringify({ endpoint_id: endpointId, event_ids: acked }) }); } } catch (err) { console.error('Poll error:', err); await new Promise(r => setTimeout(r, 5000)); // Back off on error } }}Python
Section titled “Python”import requestsimport time
def poll_loop(endpoint_id: str, api_key: str): base_url = "https://app.mittr.io/api/v1" headers = {"X-API-Key": api_key}
while True: try: res = requests.get( f"{base_url}/poll", params={"endpoint_id": endpoint_id, "limit": 50, "timeout": 30}, headers=headers, timeout=35, # slightly longer than poll timeout ) events = res.json().get("events", [])
if not events: continue
acked = [] for event in events: try: process_event(event) acked.append(event["id"]) except Exception as e: print(f"Failed to process {event['id']}: {e}")
if acked: requests.post( f"{base_url}/poll/ack", json={"endpoint_id": endpoint_id, "event_ids": acked}, headers={**headers, "Content-Type": "application/json"}, ) except Exception as e: print(f"Poll error: {e}") time.sleep(5)When to use poll vs push
Section titled “When to use poll vs push”| Push (default) | Poll | |
|---|---|---|
| Consumer has public URL | Yes | Not required |
| Real-time latency | Sub-second | Depends on poll interval |
| Rate control | Mittr controls rate | Consumer controls rate |
| Behind firewall | Needs ingress | Works with egress only |
| Scaling | Mittr distributes load | Consumer pulls at own pace |
Use push delivery for most cases. Use poll when your consumer can’t accept inbound connections or needs precise control over processing rate.