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.

Use Xquik in Zapier when a workflow needs X (Twitter) search, account lookups, trends, publishing, extraction jobs, monitors, or webhook automation without an X Developer app. Start with a private Zapier Platform CLI integration. Keep the first release focused on high-volume workflow primitives, then expand once real Zaps show which endpoints users need.

Prerequisites

  • Xquik API key
  • Zapier account with Platform CLI access
  • Node.js 18+
  • HTTPS callback URLs for REST Hook testing
Install and sign in to the Zapier CLI:
npm install -g zapier-platform-cli
zapier login
zapier init xquik-zapier --template minimal
cd xquik-zapier
npm install

Integration Shape

Auth

API key field named apiKey, injected as x-api-key.

Base URL

https://xquik.com/api/v1

Request Helper

JSON requests, structured Xquik errors, and Retry-After handling.

Actions

Search Tweets, Get Tweet, Get User, Get Trends, Create Tweet, Create Reply, Create Extraction, Create Monitor, and Create Webhook.

Triggers

New Matching Tweet polling, Monitor Event instant trigger, Extraction Completed polling, and Webhook Delivery Failure polling.
This gives Zapier builders API-key auth, 120 REST endpoints, monitor webhooks, extraction jobs, and agent-adjacent workflows. The visible Zapier X templates are narrower: they focus on polling a query and taking one write action.

API Key Auth

Add a custom auth field and inject it into every Xquik request:
const BASE_URL = "https://xquik.com/api/v1";

function addApiKeyHeader(request, z, bundle) {
  request.headers = request.headers || {};
  request.headers["x-api-key"] = bundle.authData.apiKey;
  return request;
}

async function testAuth(z) {
  const response = await z.request({
    method: "GET",
    url: `${BASE_URL}/account`,
  });

  return response.data;
}

module.exports = {
  authentication: {
    type: "custom",
    fields: [{ key: "apiKey", label: "Xquik API Key", required: true }],
    test: testAuth,
  },
  beforeRequest: [addApiKeyHeader],
};

Shared Error Handling

Normalize Xquik responses in one helper so every action reports the same remediation:
function xquikErrorMessage(status, data, headers) {
  if (status === 401) {
    return "Authentication failed. Check the Xquik API key.";
  }

  if (status === 402) {
    return "Subscription or credits required. Update billing in Xquik.";
  }

  if (status === 429) {
    const retryAfter = headers?.["retry-after"];
    return retryAfter
      ? `Rate limited. Retry after ${retryAfter} seconds.`
      : "Rate limited. Retry after the cooldown period.";
  }

  return data?.message || data?.error || "Xquik request failed.";
}

function throwForXquikError(z, response) {
  if (response.status < 400) {
    return;
  }

  throw new z.errors.Error(
    xquikErrorMessage(response.status, response.data, response.headers),
    "XquikError",
    response.status,
  );
}
Call throwForXquikError(z, response) after each z.request.

Starter Actions

Search Tweets

Call GET /x/tweets/search with q; use cursor for page loops or limit for bounded pulls.

Get Tweet

Call GET /x/tweets/{id} with a tweet ID.

Get User

Call GET /x/users/{id} with a user ID.

Get Trends

Call GET /x/trends with optional woeid and count.

Create Tweet

Call POST /x/tweets with account, text, and optional public media URLs.

Create Reply

Call POST /x/tweets with account, text, and reply_to_tweet_id.

Create Extraction

Call POST /extractions with toolType, query fields, and result limit.

Create Monitor

Call POST /monitors with username and event types.

Create Webhook

Call POST /webhooks with callback URL and event types.

Result Handoff

Use Zapier samples and outputFields so later Zap steps map stable values. Return compact objects from actions and arrays from triggers; do not pass full API responses into Zap history, Slack messages, CRM rows, or retry queues.

Search Tweets action

Return tweet rows with id, text, author__username, createdAt, and optional url; carry has_next_page and next_cursor when a Zap loops pages.

User profile rows

Return source id as user_id, plus username, name, followers, verified, profilePicture, has_next_page, next_cursor, and the lookup or search input.

Trend rows

Return each trend name, rank, query, and description. Keep response count, woeid, and the selected region with the Zap run.

Tweet or Reply write

Return tweetId, charged, and chargedCredits on 200 Success. For 202 x_write_unconfirmed, return writeActionId, status, charged, and chargedCredits, then poll GET /x/write-actions/{id} before retrying.

Public media upload

Return mediaId, mediaUrl, and success. Pass mediaUrl to POST /x/tweets in media; reserve uploaded media IDs for one-item DMs.

Monitor and webhook setup

Return monitor id, username, xUserId, eventTypes, isActive, and nextBillingAt; return webhook id, url, eventTypes, and one-time secret. For Zap storage rows, map production deliveryId to delivery_id for receiver retry de-dupe and streamEventId to stream_event_id when one monitor event should process once across endpoint changes.

REST Hook trigger

Return id, deliveryId, and streamEventId; choose deliveryId for endpoint retry de-dupe or streamEventId when one monitor event should process once across webhook changes.

Extraction polling trigger

Return completed job id, toolType, and status; fetch detail rows and carry hasMore plus nextCursor into batch Zaps.
Use a Zapier dropdown to map friendly region names to WOEID values before calling Xquik. Example search action:
async function performSearchTweets(z, bundle) {
  const response = await z.request({
    method: "GET",
    url: `${BASE_URL}/x/tweets/search`,
    params: {
      q: bundle.inputData.q,
      limit: bundle.inputData.limit || 25,
    },
  });

  throwForXquikError(z, response);
  return response.data.tweets || [];
}

module.exports = {
  key: "search_tweets",
  noun: "Tweet",
  display: {
    label: "Search Tweets",
    description: "Find recent tweets that match a search query.",
  },
  operation: {
    inputFields: [
      { key: "q", label: "Query", required: true, type: "string" },
      { key: "limit", label: "Limit", required: false, type: "integer" },
    ],
    perform: performSearchTweets,
    sample: {
      id: "1840000000000000000",
      text: "Example tweet text",
      author: { username: "xquikcom" },
      url: "https://x.com/xquikcom/status/1840000000000000000",
    },
    outputFields: [
      { key: "id", label: "Tweet ID" },
      { key: "text", label: "Text" },
      { key: "author__username", label: "Author Username" },
      { key: "url", label: "URL" },
    ],
  },
};

Trigger 1: New Matching Tweet

Use polling for query-based alerts. Return a stable array of tweet records and let Zapier deduplicate by id.
async function performNewMatchingTweet(z, bundle) {
  const response = await z.request({
    method: "GET",
    url: `${BASE_URL}/x/tweets/search`,
    params: {
      q: bundle.inputData.q,
      limit: 25,
    },
  });

  throwForXquikError(z, response);
  return response.data.tweets || [];
}

Trigger 2: Monitor Event REST Hook

Use REST Hooks for monitor events so Zapier receives new tweets, replies, quotes, and retweets immediately.

Subscribe

async function subscribeHook(z, bundle) {
  const response = await z.request({
    method: "POST",
    url: `${BASE_URL}/webhooks`,
    body: {
      url: bundle.targetUrl,
      eventTypes: bundle.inputData.eventTypes,
    },
  });

  throwForXquikError(z, response);
  return { id: response.data.id };
}

Unsubscribe

async function unsubscribeHook(z, bundle) {
  const response = await z.request({
    method: "DELETE",
    url: `${BASE_URL}/webhooks/${bundle.subscribeData.id}`,
  });

  throwForXquikError(z, response);
  return response.data;
}

Perform

function performMonitorEvent(z, bundle) {
  const payload = bundle.cleanedRequest;

  return [
    {
      id: payload.streamEventId || payload.deliveryId,
      deliveryId: payload.deliveryId,
      eventType: payload.eventType,
      occurredAt: payload.occurredAt,
      username: payload.username,
      tweetId: payload.data?.id,
      text: payload.data?.text,
      authorUserName: payload.data?.author?.userName || payload.username,
    },
  ];
}
Use performList to return one recent monitor event with the same schema. Zapier requires sample output fields that match live webhook payloads.

Trigger 3: Extraction Completed

Use polling when users want bulk jobs without webhook setup:
async function performCompletedExtractions(z) {
  const response = await z.request({
    method: "GET",
    url: `${BASE_URL}/extractions`,
    params: { status: "completed", limit: 25 },
  });

  throwForXquikError(z, response);
  return response.data.extractions || [];
}

Trigger 4: Webhook Delivery Failure

Use polling for operations teams that need delivery alerts:
async function performWebhookFailures(z, bundle) {
  const response = await z.request({
    method: "GET",
    url: `${BASE_URL}/webhooks/${bundle.inputData.webhookId}/deliveries`,
  });

  throwForXquikError(z, response);
  return (response.data.deliveries || []).filter(
    (delivery) => delivery.status === "failed",
  );
}

Test Coverage

Add focused Zapier tests before sharing the private app:

Auth Header Injection

Every request includes x-api-key from bundle.authData.apiKey.

Invalid Key

401 returns “Authentication failed. Check the Xquik API key.”

Rate Limit

429 includes Retry-After in the user-facing message when present.

REST Hook Subscribe

POST /webhooks sends bundle.targetUrl and selected event types.

REST Hook Unsubscribe

DELETE /webhooks/{id} uses bundle.subscribeData.id.

Sample Output

Trigger samples include id, eventType, occurredAt, tweet text, and author username.

Search Action

Search returns an array of tweets with stable IDs.
Run the local Zapier suite with:
zapier-platform test
zapier-platform validate

Launch Checklist

  • Keep the first version private until auth, REST Hook lifecycle, sample output, and rate-limit behavior are verified.
  • Use clear labels in the Zap editor: Search Tweets, Create Tweet, Monitor Event, Extraction Completed.
  • Document which actions consume credits before publishing to a broader team.
  • Add more endpoints only when Zap history shows repeated manual API Request steps.

Next Steps

  • Read API Reference for auth, rate limits, and errors.
  • Read Webhooks for payload shape and retries.
  • Read Extraction Workflow for job creation and result pagination.
  • Use n8n when the team prefers visual workflows without a custom Zapier app.
Last modified on May 18, 2026