Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.xquik.com/llms.txt

Use this file to discover all available pages before exploring further.

Webhooks deliver events from account or keyword monitors to your server in real time. Every delivery is signed with HMAC-SHA256 so you can verify authenticity. Use webhooks when tweet.new, tweet.reply, tweet.quote, tweet.retweet, tweet.media, tweet.link, tweet.poll, tweet.mention, tweet.hashtag, tweet.longform, profile.avatar.changed, profile.banner.changed, profile.name.changed, profile.username.changed, profile.bio.changed, profile.location.changed, profile.url.changed, profile.verified.changed, profile.protected.changed, profile.pinned_tweet.changed, or profile.unavailable.changed events from tracked accounts must reach your app without polling. Keyword monitors support tweet event types only. The setup returns a monitor ID, webhook ID, one-time signing secret, and signed JSON deliveries. Webhook operations are free. Active monitors cost 21 credits/hour and include stored events plus webhook delivery.

Account or keyword monitor

Output: monitor ID, username or query, and selected event types. Cost: 21 credits/hour while active.

Webhook endpoint

Output: webhook ID, URL, event types, and one-time secret. Cost: free.

Signed delivery

Output: HTTPS POST with JSON body and HMAC headers. Cost: included with the active monitor.

Choose the webhook source

Account activity

Create POST /monitors when one X account should emit selected tweet and profile event types. Store monitorId, username, xUserId, and eventTypes.

Keyword matches

Create POST /monitors/keywords when a query should emit matching tweet events. Store keywordMonitorId, query, and eventTypes.

Receiver endpoint

Create POST /webhooks after the monitor. Store the webhook id, URL, selected eventTypes, and one-time secret before sending tests.

Replay and audit

Use GET /events for stored monitor events and GET /webhooks/{id}/deliveries for delivery attempts. Join on streamEventId.

Quick setup

Get webhooks working in 3 steps:
1

Create a monitor

Choose an account monitor for one X account, or a keyword monitor for matching query results.
curl -X POST https://xquik.com/api/v1/monitors \
  -H "x-api-key: xq_YOUR_KEY_HERE" \
  -H "Content-Type: application/json" \
  -d '{
    "username": "elonmusk",
    "eventTypes": ["tweet.new", "tweet.reply"]
  }' | jq
Store the returned monitor id; account events include username, keyword events include query.
2

Register a webhook

Provide an HTTPS URL and select which event types to receive. Xquik generates a signing secret. Store it securely, it is only returned once.
curl -X POST https://xquik.com/api/v1/webhooks \
  -H "x-api-key: xq_YOUR_KEY_HERE" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-server.com/webhook",
    "eventTypes": ["tweet.new", "tweet.reply"]
  }' | jq
Response:
{
  "id": "15",
  "url": "https://your-server.com/webhook",
  "eventTypes": ["tweet.new", "tweet.reply"],
  "secret": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2",
  "createdAt": "2026-02-24T10:30:00.000Z"
}
3

Verify signatures

When events arrive, verify the X-Xquik-Signature header using your webhook secret to confirm authenticity. See Signature Verification for implementation details.Send a test payload before connecting production logic:
curl -X POST https://xquik.com/api/v1/webhooks/15/test \
  -H "x-api-key: xq_YOUR_KEY_HERE" | jq

How it works

Account or keyword monitor event -> Xquik -> Your Webhook Endpoint

Delivery format

Webhook events are delivered as HTTPS POST requests.

Headers

Content-Type

application/json. Payloads are always JSON.

User-Agent

xquik-webhooks/1.0 (+https://xquik.com). Identifies Xquik traffic.

X-Xquik-Timestamp

Unix epoch milliseconds. Used in the signing string and for replay window enforcement.

X-Xquik-Nonce

16 random bytes in hex. Reject duplicates within the replay window.

X-Xquik-Signature

sha256=HMAC_HEX_DIGEST. HMAC-SHA256 of <timestamp>.<nonce>.<rawBody>.

Payload body

{
  "eventType": "tweet.new",
  "schemaVersion": 1,
  "deliveryId": "502",
  "streamEventId": "9001",
  "occurredAt": "2026-02-24T14:22:00.000Z",
  "username": "elonmusk",
  "data": {
    "id": "1893456789012345678",
    "text": "The future is now.",
    "author": {
      "id": "44196397",
      "userName": "elonmusk",
      "name": "Elon Musk"
    },
    "isRetweet": false,
    "isReply": false,
    "isQuote": false,
    "createdAt": "2026-02-24T14:22:00.000Z"
  }
}

eventType

Type string. Event type selected by the source monitor and webhook.

schemaVersion

Type number. Webhook payload schema version. Current value is 1.

deliveryId

Type string. Webhook delivery attempt ID. Store it as the delivery-level idempotency key and use it for delivery-log correlation.

streamEventId

Type string. Stored monitor event ID. Store it as the event-level de-dupe key when one monitor event should be processed once across webhook retries or endpoint changes.

occurredAt

Type string. ISO timestamp for when the event occurred.

username

Type string. X username for account monitor events. Omitted for keyword-only monitor events and webhook.test.

query

Type string. Keyword query that matched the event. Present for keyword monitor events.

data

Type object. Raw event object for the monitored tweet activity.
The data field contains the raw tweet object for the monitor event. Fields may vary by tweet type.

Receiver storage row

After signature verification succeeds, store a compact receiver row before handing the event to workers. Use deliveryId for delivery-level retries and streamEventId for event-level processing. Do not store endpoint signing values, the raw request body, the raw signature, or full headers in shared incident rows.
{
  "record_type": "webhook_receiver_event",
  "webhook_id": "15",
  "delivery_id": "502",
  "stream_event_id": "9001",
  "event_type": "tweet.new",
  "source": "account",
  "username": "elonmusk",
  "signature_verified": true,
  "nonce_cache_key": "webhook:15:nonce_hash",
  "occurred_at": "2026-02-24T14:22:00.000Z",
  "receiver_status": 202,
  "event_join": "GET /api/v1/events/9001",
  "delivery_log": "GET /api/v1/webhooks/15/deliveries"
}

Event data shapes

Each event type includes a data object. Tweet events contain the raw tweet. The webhook.test event contains a test message and timestamp. The examples below show the most common fields.

tweet.new

A new original tweet posted by the monitored account.
{
  "eventType": "tweet.new",
  "username": "elonmusk",
  "data": {
    "id": "1893456789012345678",
    "text": "The future is now.",
    "author": {
      "id": "44196397",
      "userName": "elonmusk",
      "name": "Elon Musk"
    },
    "isRetweet": false,
    "isReply": false,
    "isQuote": false,
    "createdAt": "2026-02-24T14:22:00.000Z"
  }
}

tweet.quote

A quote tweet posted by the monitored account.
{
  "eventType": "tweet.quote",
  "username": "elonmusk",
  "data": {
    "id": "1893456789012345679",
    "text": "Interesting take on this.",
    "author": {
      "id": "44196397",
      "userName": "elonmusk",
      "name": "Elon Musk"
    },
    "isRetweet": false,
    "isReply": false,
    "isQuote": true,
    "quoted_tweet": {
      "id": "1893400000000000000",
      "text": "Our latest launch was a success.",
      "author": {
        "userName": "SpaceX"
      }
    },
    "createdAt": "2026-02-24T15:10:00.000Z"
  }
}

tweet.reply

A reply posted by the monitored account.
{
  "eventType": "tweet.reply",
  "username": "elonmusk",
  "data": {
    "id": "1893456789012345680",
    "text": "Great question. Working on it.",
    "author": {
      "id": "44196397",
      "userName": "elonmusk",
      "name": "Elon Musk"
    },
    "isRetweet": false,
    "isReply": true,
    "isQuote": false,
    "inReplyToId": "1893411111111111111",
    "createdAt": "2026-02-24T16:30:00.000Z"
  }
}

tweet.retweet

A retweet posted by the monitored account.
{
  "eventType": "tweet.retweet",
  "username": "elonmusk",
  "data": {
    "id": "1893456789012345681",
    "text": "RT @xai: Exciting news today.",
    "author": {
      "id": "44196397",
      "userName": "elonmusk",
      "name": "Elon Musk"
    },
    "isRetweet": true,
    "isReply": false,
    "isQuote": false,
    "createdAt": "2026-02-24T17:00:00.000Z"
  }
}

webhook.test

A test payload sent via the Test Webhook endpoint to verify your endpoint is reachable.
{
  "eventType": "webhook.test",
  "data": {
    "message": "Test delivery from Xquik"
  },
  "timestamp": "2026-02-27T12:00:00.000Z"
}

Retry policy

Failed deliveries are retried with exponential backoff (base 1 second, multiplier 2x, max 60 seconds):

Attempts 1-3

Delays: 1 second, 2 seconds, then 4 seconds.

Attempts 4-6

Delays: 8 seconds, 16 seconds, then 32 seconds.

Attempts 7-9

Delay: 60 seconds for each attempt after the cap is reached.

Attempt 10

Final attempt. If it fails, the delivery is marked as exhausted.
After the 10th failed attempt, the delivery is marked as exhausted. A 410 Gone response exhausts the delivery immediately. Check delivery status via the deliveries endpoint.
Retries are processed in batches, so actual delay may be slightly longer than shown.
Terminal failures: Return 410 Gone only when Xquik should stop retrying that delivery. Other non-2xx responses and network failures retry until the delivery is exhausted.

Backfill after a receiver outage

Use this handoff after your receiver was down, returned repeated non-2xx responses, or exhausted deliveries. Fix the receiver first, then use delivery rows to identify failed attempts and stored event pages to rebuild downstream work. Do not use 410 Gone for temporary throttling; it exhausts that delivery.
{
  "record_type": "webhook_receiver_backfill",
  "webhook_id": "15",
  "delivery_log": "GET /api/v1/webhooks/15/deliveries",
  "event_backfill_endpoint": "GET /api/v1/events?limit=100&after={nextCursor}",
  "source_filter": "monitorId for account monitors, keywordMonitorId for keyword monitors",
  "join_key": "delivery.streamEventId == event.id",
  "resume_fields": [
    "deliveryId",
    "streamEventId",
    "status",
    "attempts",
    "lastStatusCode",
    "lastError",
    "nextCursor"
  ],
  "stop_when": "hasMore is false",
  "handoff_state": "receiver_fixed_page_events_join_deliveries"
}
Store nextCursor after every event page. Reprocess events whose id matches failed or exhausted delivery streamEventId values, then leave delivered rows alone. Scope event pages with monitorId for account monitors or keywordMonitorId for keyword monitors when the source is known; omit both only for all-monitor replay.

Troubleshoot a delivery

Use this handoff when a receiver fails tests, repeats failures, or reaches an exhausted delivery state.
{
  "record_type": "webhook_delivery_troubleshooting",
  "webhook_id": "15",
  "signed_test": "POST /api/v1/webhooks/15/test",
  "delivery_log": "GET /api/v1/webhooks/15/deliveries",
  "event_join": "GET /api/v1/events/{id}",
  "event_id_source": "streamEventId",
  "route_on": [
    "status",
    "attempts",
    "lastStatusCode",
    "lastError",
    "createdAt",
    "deliveredAt"
  ],
  "test_payload_has_ids": false,
  "production_payload_ids": ["deliveryId", "streamEventId"],
  "handoff_state": "verify_signature_check_delivery_join_event"
}

Signed receiver test

Run Test Webhook after changing endpoint code, secrets, firewall rules, or queue routing. Treat success: true with a 2xx statusCode as receiver proof.

Signature and IDs

Verify X-Xquik-Signature, X-Xquik-Timestamp, and X-Xquik-Nonce on the raw request body. webhook.test omits deliveryId and streamEventId; production deliveries include both IDs.

Delivery triage

Check List Deliveries for status, attempts, lastStatusCode, lastError, createdAt, and deliveredAt. Page on exhausted, warn on repeated failed, and ignore delivered.

Event context

Join streamEventId to Get Event when the receiver owner needs the original monitor event, tweet fields, username, or keyword query that triggered the delivery.

Requirements

  • Endpoint must use HTTPS
  • Endpoint must not resolve to a private or internal IP address (localhost, 10.x.x.x, 172.16-31.x.x, 192.168.x.x, 169.254.x.x)
  • Endpoints should respond promptly with a 2xx status code. Non-2xx responses count as failures and trigger retries

Where to go next

Webhook API reference

Create, list, update, deactivate, test, and inspect webhook deliveries.

Signature Verification

Verify HMAC-SHA256 signatures and implement idempotency.

Testing Webhooks

Test webhook delivery locally with tunnels and mock payloads.

MCP equivalent

Use xquik.request('/api/v1/webhooks', ...) for create, list, update, delete, and test.

Monitor setup

Create account monitors that emit events for webhook delivery.

Keyword monitor setup

Create keyword monitors that emit matching tweet events for webhook delivery.
Last modified on May 24, 2026