> ## 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.

# Pipedream automation for Twitter API & webhooks

> Build Pipedream workflow automation for tweet search, follower exports, Twitter monitors, signed webhooks, scheduled reads, and approved posts through Xquik.

<blockquote className="agent-llms-directive">
  For the complete documentation index, see <a href="/llms.txt">llms.txt</a>.
</blockquote>

Build a Pipedream Twitter integration for searches, profiles, monitors, and approved posts.
Xquik supplies one REST API and one API key for every workflow.

The initial package contains 1 app file, 8 actions, and 2 sources.
Add another action after workflows repeatedly need the same HTTP request.

## Choose a Pipedream automation pattern

Pipedream Workflows combine one trigger with actions or code steps.
An HTTP trigger receives signed Xquik monitor events.
A schedule trigger starts tweet search automation or extraction polling.
An RSS trigger can start an approved publishing queue.

Choose a private component for actions shared by multiple team members.
Choose a custom JavaScript step for one custom API integration.
The workflow uses prebuilt actions for Slack, Google Sheets, and CRM handoffs.
Keep one output per workflow: tweet alerts, profile rows, or approved posts.

Pipedream workflow automation becomes fragile when unrelated jobs share one trigger.
Split searches, monitor events, follower exports, and approved writes.
These boundaries create small, testable paths.
Separate workflows expose each job's errors and rate limits.

This Pipedream automation platform can replace manual tasks like copying tweets.
It should never hide approval for tweets, replies, or direct messages.
Review every write payload before the workflow sends it.

This guide calls Xquik routes directly.
It does not require Pipedream's native Twitter integration.

## Build a serverless Twitter API integration

This serverless API integration runs without a dedicated workflow server.
Start every Xquik request at `https://xquik.com/api/v1`.
Send the API key through the `x-api-key` header.
Pipedream secret props should contain all API keys.
Step exports, logs, and error messages must exclude these keys.

`GET /x/tweets/search` supports each scheduled Twitter automation workflow.
Keep the query, filters, limit, and opaque cursor between pages.
Destinations should store tweet IDs after accepting each row.
This order prevents skipped tweets after partial failures.

`GET /x/users/{id}` returns the profile fields required for enrichment.
Export usernames, follower counts, verification state, and profile images.
Use `POST /extractions` when exports require multiple API pages.
Poll the returned job until it reaches a terminal status.

Custom JavaScript automation can read `steps.trigger.event` after a trigger.
HTTP events include method, body, headers, path, query, and URL fields.
Later steps receive tweet IDs, text, usernames, cursors, and destination keys.
Never export signing secrets, raw signatures, or complete request headers.

A shared request helper keeps API integrations consistent.
It should normalize statuses, summaries, cursors, and retry instructions.
Name every step after its concrete output.
Examples include `search_tweets`, `normalize_profiles`, and `send_slack_alert`.

## Prerequisites

* [Xquik API key](/x-api-quickstart)
* Pipedream account
* Node.js supported by the current Pipedream CLI
* Pipedream CLI installed and signed in

```bash theme={null}
npm install -g @pipedream/cli
pd login
```

## Component shape

<CardGroup cols={2}>
  <Card title="App" icon="app-window">
    `components/xquik/app/xquik.app.ts`
  </Card>

  <Card title="Auth" icon="key-round">
    API key prop injected as `x-api-key`.
  </Card>

  <Card title="Base URL" icon="link">
    `https://xquik.com/api/v1`
  </Card>

  <Card title="Actions" icon="play">
    Get Tweet, Search Tweets, Get User, Get Trends, Create Tweet, Create Extraction, Create Monitor, and Create Webhook.
  </Card>

  <Card title="Sources" icon="radio">
    Monitor Event Webhook and Extraction Completed Polling.
  </Card>

  <Card title="Shared helper" icon="workflow">
    JSON requests, structured Xquik errors, and `Retry-After` handling.
  </Card>
</CardGroup>

## App file

Create the shared app component first:

```typescript theme={null}
import { axios } from "@pipedream/platform";

export default {
  type: "app",
  app: "xquik",
  propDefinitions: {
    apiKey: {
      type: "string",
      label: "Xquik API Key",
      secret: true,
    },
  },
  methods: {
    async request($, config, apiKey) {
      return axios($, {
        ...config,
        baseURL: "https://xquik.com/api/v1",
        headers: {
          "content-type": "application/json",
          "x-api-key": apiKey,
          ...(config.headers || {}),
        },
      });
    },
  },
};
```

Add `apiKey: { propDefinition: [xquik, "apiKey"] }` to each action and source
that calls `xquik.request`.

Use `GET /account` as the first authentication check.
It verifies the API key without changing an X account.

## Shared error handling

Wrap requests so every action and source reports the same remediation:

```typescript theme={null}
function xquikErrorMessage(status: number, body: unknown, headers: Record<string, string>) {
  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.";
  }
  if (typeof body === "object" && body !== null && "message" in body) {
    return String((body as { message: unknown }).message);
  }
  return "Xquik request failed.";
}
```

Call the helper once per request.
Export a short `$summary` so each workflow run stays scannable.

## Control errors, retries, and rate limits

Route each documented Xquik status before a Pipedream step exports anything.
A `400` response means the request needs different fields.
A `401` response means the API key failed authentication.
A `402` response requires a subscription or credit change.
A `404` response identifies a missing tweet, profile, monitor, or job.

A `424` response reports an upstream dependency failure.
A `429` response means the workflow exceeded a rate limit.
A `502` response reports a temporary retrieval failure.
Read `Retry-After` when the response includes it.

Automatic retries should exclude `400`, `401`, `402`, and `404`.
Safe reads can retry `424`, `429`, or `502` with bounded backoff.
Write retries must follow the returned `safeToRetry` field.
Send a new idempotency key only when the contract permits another attempt.

Use Pipedream concurrency controls for fixed workflow execution limits.
Concurrency limits do not replace endpoint rate limits.
Place search and profile actions behind one shared throttle policy.
Place tweet and reply writes behind a separate approval queue.

Store a page cursor only after downstream processing succeeds.
The workflow can rerun a failed page and upsert by tweet or profile ID.
This strategy protects Slack alerts, CRM rows, and warehouse loads.

## Starter actions

<CardGroup cols={2}>
  <Card title="Get tweet" icon="message-square">
    Call `GET /x/tweets/{id}` and return one tweet.
  </Card>

  <Card title="Search tweets" icon="search">
    Call `GET /x/tweets/search` and return an array of tweets.
  </Card>

  <Card title="Get user" icon="user">
    Call `GET /x/users/{id}` and return one user.
  </Card>

  <Card title="Get trends" icon="trending-up">
    Call `GET /x/trends` and return a trend list.
  </Card>

  <Card title="Create tweet" icon="send">
    Call `POST /x/tweets` and return created tweet metadata.
  </Card>

  <Card title="Create extraction" icon="database">
    Call `POST /extractions` and return the job ID and status.
  </Card>

  <Card title="Create monitor" icon="radio">
    Call `POST /monitors` and return the monitor ID and status.
  </Card>

  <Card title="Create webhook" icon="webhook">
    Call `POST /webhooks` and return the webhook ID and signing secret.
  </Card>
</CardGroup>

Example Search Tweets action:

```typescript theme={null}
import xquik from "../../app/xquik.app";

export default {
  key: "xquik-search-tweets",
  name: "Search Tweets",
  description: "Search recent X posts with Xquik.",
  version: "0.0.1",
  type: "action",
  props: {
    xquik,
    apiKey: { propDefinition: [xquik, "apiKey"] },
    q: { type: "string", label: "Query" },
    limit: { type: "integer", label: "Limit", optional: true, default: 25 },
  },
  async run({ $ }) {
    const data = await this.xquik.request(
      $,
      {
        method: "GET",
        url: "/x/tweets/search",
        params: { q: this.q, limit: this.limit },
      },
      this.apiKey,
    );

    $.export("$summary", `Found ${(data.tweets || []).length} tweets.`);
    return data.tweets || [];
  },
};
```

## Result handoff

Pipedream exports and source metadata pass stable fields between workflow steps.
Destinations should receive normalized fields, not complete API responses.

<CardGroup cols={2}>
  <Card title="Search tweets action" icon="search">
    Export `tweet_count`, `has_more`, and `next_cursor`. Return tweet rows with `tweet_id`, `text`, `author_username`, `created_at`, and optional `url`.
  </Card>

  <Card title="User profile action" icon="users">
    Export `user_id`, `username`, `name`, `followers`, `verified`, and `profile_picture`. Return one profile row for `GET /x/users/{id}`.
  </Card>

  <Card title="Trend rows" icon="trending-up">
    Export `trend_count` and `woeid`. Return trend rows with `name`, `rank`, `query`, and `description`, then keep the selected region with workflow event metadata.
  </Card>

  <Card title="Tweet or reply write" icon="send">
    Send a unique `Idempotency-Key`. Export `id`, `status`, `billing`, `result`, and `statusUrl`. Poll while `terminal` is false. Retry only when `safeToRetry` is true, using a new key.
  </Card>

  <Card title="Media attachments" icon="image">
    For tweets or replies, pass public URLs in `media` and export `tweet_id` or `write_action_id`. For DMs, upload first, pass one `media_id` in `media_ids`, export `message_id`, and leave `reply_to_message_id` unset.
  </Card>

  <Card title="Monitor and webhook setup" icon="radio">
    Export monitor `id`, `username`, `xUserId`, `eventTypes`, `isActive`, and `nextBillingAt`. Export webhook `id`, `url`, `eventTypes`, and one-time `secret`. For Pipedream data stores, map production `deliveryId` to `delivery_id` for receiver retry deduplication. Map `streamEventId` to `stream_event_id` when one monitor event should process once across endpoint changes.
  </Card>

  <Card title="Monitor event source" icon="fingerprint">
    Emit `deliveryId` for endpoint-level retry deduplication, `streamEventId` for event-level deduplication across endpoint changes, and `occurredAt` as `ts`.
  </Card>

  <Card title="Stored event replay" icon="activity">
    Call `GET /api/v1/events` with `cursor` when a workflow needs replay. Export `event_id`, `type`, `monitor_id`, `monitor_type`, `occurred_at`, `has_more`, and `next_cursor`.
  </Card>

  <Card title="Receiver acceptance" icon="copy-check">
    Return `2xx` after accepting duplicate `deliveryId` or `streamEventId`. Keep endpoint signing values, raw request body, raw signature, and full headers out of step exports, logs, data stores, Slack messages, CRM rows, and retry queues.
  </Card>

  <Card title="Extraction polling source" icon="database">
    Emit completed job `id`, `tool_type`, and `status`. Fetch detail rows and carry `has_more` plus `next_cursor` into warehouse batches.
  </Card>
</CardGroup>

## Source 1: monitor event webhook

This source delivers immediate tweet, reply, quote, and repost alerts.

Setup flow:

1. Pipedream creates an HTTP endpoint for the source.
2. The source calls `POST /webhooks` with that endpoint and selected event types.
3. The user creates or selects an Xquik monitor.
4. Each webhook payload emits one event with a stable ID.

Payload mapping:

<CardGroup cols={3}>
  <Card title="Event ID" icon="fingerprint">
    Map Pipedream `id` to `streamEventId` for event-level deduplication, or `deliveryId` for endpoint-level deduplication.
  </Card>

  <Card title="Event type" icon="bell">
    Map `eventType` to route `tweet.new`, `tweet.reply`, `tweet.quote`, and `tweet.retweet` events.
  </Card>

  <Card title="Occurred at" icon="calendar-clock">
    Map `occurredAt` as the event timestamp.
  </Card>

  <Card title="Username" icon="at-sign">
    Map `username` for account monitor events.
  </Card>

  <Card title="Tweet ID" icon="hash">
    Map `data.id` as the tweet identifier.
  </Card>

  <Card title="Text" icon="type">
    Map `data.text` as the tweet body.
  </Card>

  <Card title="Author username" icon="user-round">
    Map `data.author.userName` when present. Use `username` as the monitored-account fallback.
  </Card>
</CardGroup>

Keep the webhook secret returned by Xquik and verify `x-xquik-signature` before emitting events.

## Build event-driven Twitter workflows

Event driven workflows start when Xquik delivers a monitor event.
Account monitors can identify new tweets, replies, quotes, and reposts.
Keyword monitors can identify matching tweets without repeated broad searches.

Verify HMAC against the exact request body before parsing JSON.
Reject stale timestamps and reused nonces before starting downstream steps.
Use `deliveryId` for endpoint retry deduplication.
Use `streamEventId` for event deduplication across endpoint changes.

Pipedream data stores can retain these identifiers with expiration times.
Their operations are not atomic transactions.
Design every CRM upsert and Slack notification for repeated delivery.
Return `2xx` after accepting an already processed event.

Real-time synchronization should keep the event timestamp and monitor ID.
Separate filters should route replies, quotes, and reposts.
This separation gives marketing campaigns and support teams clearer alerts.

A Twitter monitor webhook should send only verified event fields downstream.
Keep raw bodies and signature headers out of workflow exports.
Use stored event replay when a destination recovers after downtime.

## Source 2: extraction completed polling

Use this when teams want batch jobs without webhook setup.

```typescript theme={null}
export default {
  key: "xquik-extraction-completed",
  name: "Extraction Completed",
  description: "Emit completed Xquik extraction jobs.",
  version: "0.0.1",
  type: "source",
  props: {
    xquik,
    apiKey: { propDefinition: [xquik, "apiKey"] },
    timer: { type: "$.interface.timer", default: { intervalSeconds: 900 } },
  },
  async run() {
    const data = await this.xquik.request(
      this,
      {
        method: "GET",
        url: "/extractions",
        params: { status: "completed", limit: 25 },
      },
      this.apiKey,
    );

    for (const job of data.extractions || []) {
      this.$emit(job, {
        id: job.id,
        summary: `Extraction ${job.id} completed`,
        ts: Date.parse(job.completedAt || job.updatedAt || job.createdAt),
      });
    }
  },
};
```

## Recipes

### Search tweets to Slack

<CardGroup cols={2}>
  <Card title="Schedule trigger" icon="calendar-clock">
    Run the workflow on the reporting cadence.
  </Card>

  <Card title="Xquik search tweets" icon="search">
    Call the Search Tweets action and return recent matching posts.
  </Card>

  <Card title="Engagement filter" icon="funnel">
    Keep only tweets that meet the minimum engagement threshold.
  </Card>

  <Card title="Slack send message" icon="message-square">
    Send the selected tweet text, author, and link to the channel.
  </Card>
</CardGroup>

### Monitor events to CRM

<CardGroup cols={2}>
  <Card title="Monitor event source" icon="radio">
    Receive Xquik monitor events from the webhook source.
  </Card>

  <Card title="Event type filter" icon="funnel">
    Route `tweet.new`, `tweet.reply`, `tweet.quote`, and `tweet.retweet` events separately.
  </Card>

  <Card title="Get user enrichment" icon="user">
    Enrich the event with the Get User action before CRM routing.
  </Card>

  <Card title="CRM upsert" icon="database">
    Upsert by user ID to avoid duplicate account records.
  </Card>
</CardGroup>

### Extraction to warehouse

<CardGroup cols={2}>
  <Card title="Create extraction" icon="database">
    Start the extraction job with `POST /extractions`.
  </Card>

  <Card title="Extraction completed source" icon="radio">
    Poll for completed jobs before loading rows downstream.
  </Card>

  <Card title="Fetch extraction detail" icon="file-text">
    Fetch the completed extraction detail and result rows.
  </Card>

  <Card title="Warehouse destination" icon="database">
    Send normalized rows to the warehouse destination.
  </Card>
</CardGroup>

## Automate focused Twitter workflows

Use tweet search automation for scheduled brand, topic, or competitor searches.
Send matched tweets to Slack only after an engagement filter passes.
The deduplication step uses persisted tweet IDs to suppress repeated alerts.

Use monitor events for near-real-time lead generation signals.
Enrich the author profile before creating a CRM record.
Upsert by X user ID, not a mutable username.
Each CRM record should include the triggering tweet URL.

Use bounded follower pages for Google Sheets exports.
Use extraction jobs when exports exceed one bounded page.
Load completed rows in batches and keep the next cursor.

Use scheduled tasks for regional trends and recurring tweet searches.
Keep schedule frequency within documented Twitter API rate limits.
Record the search window so later runs avoid overlapping results.

Send every blog post and scheduled tweet through an approval queue.
An RSS item can create a draft payload.
A reviewer should approve its text, links, and target account.
The final action can then publish with an idempotency key.

These automation tools should reduce repetitive copying.
They should not automate unsolicited replies, follows, or direct messages.

## Test coverage

Add focused tests before sharing the component package:

<CardGroup cols={2}>
  <Card title="Auth injection" icon="shield-check">
    Every request includes `x-api-key` and never logs the key.
  </Card>

  <Card title="Invalid key" icon="key-round">
    `401` produces "Authentication failed. Check the Xquik API key."
  </Card>

  <Card title="Rate limit" icon="timer">
    `429` includes `Retry-After` when present.
  </Card>

  <Card title="Search action" icon="search">
    Returns an array with stable tweet IDs.
  </Card>

  <Card title="Create webhook" icon="webhook">
    Sends callback URL and selected event types.
  </Card>

  <Card title="Webhook source" icon="radio">
    Emits one event per payload with a stable ID.
  </Card>

  <Card title="Polling source" icon="database">
    Emits only completed extraction jobs.
  </Card>
</CardGroup>

Run component tests and publish privately first:

```bash theme={null}
npm test
pd publish components/xquik/actions/search-tweets/search-tweets.ts
```

## Pipedream Twitter automation questions

### What is Pipedream automation?

Pipedream automation connects triggers, API calls, code, and cloud applications.
Xquik adds tweet, profile, follower, monitor, and publishing operations.

### How do I set up Pipedream workflow automation?

Create one trigger, add an Xquik action, then test its output.
Add the destination only after the Xquik response is stable.

### How do I connect a Twitter webhook to custom code?

Use an HTTP source or trigger that keeps the exact request body.
Verify HMAC, timestamp, and nonce before running custom code.

### Which trigger fits tweet search automation?

Use a schedule for periodic searches.
Use a monitor webhook for near-real-time account or keyword events.

### Can Pipedream connect Twitter events to cloud apps?

Pipedream can send verified events to Slack, Sheets, CRMs, or warehouses.
Each handoff should normalize tweet and profile fields.

### How do serverless API integrations handle rate limits?

Honor `Retry-After`, cap concurrency, and retry only safe operations.
Store cursors after the destination confirms success.

### Can Pipedream run scheduled Twitter tasks?

Pipedream can schedule searches, trend reads, and extraction polling.
Place tweet publishing behind a separate human approval step.

### How do Pipedream CRM integrations avoid duplicate leads?

CRM integrations should upsert profiles by X user ID.
Deduplicate monitor events by `streamEventId` before creating CRM activity.

### Does this Pipedream Twitter guide need a native Twitter app?

The component calls Xquik's REST API with an Xquik API key.
The workflow does not depend on a native Twitter app.

### When should I create a private Pipedream component?

Create one when team members repeat the same authenticated request.
Use inline code for a single experimental workflow.

### How should Pipedream store webhook deduplication keys?

Store delivery and event IDs separately with suitable expiration times.
Keep downstream writes idempotent because store operations are not transactional.

### What are common Pipedream Twitter automation use cases?

Common cases include searches, profile enrichment, follower exports, and monitor alerts.
Other cases include trend reports, extraction loads, and approved posts.

## Pipedream and Xquik sources

* [Pipedream Workflows](https://pipedream.com/docs/workflows)
* [Pipedream HTTP requests](https://pipedream.com/docs/workflows/building-workflows/http)
* [Pipedream workflow triggers](https://pipedream.com/docs/workflows/building-workflows/triggers)
* [Pipedream components](https://pipedream.com/docs/components)
* [Pipedream data stores](https://pipedream.com/docs/workflows/data-management/data-stores)
* [Pipedream workflow errors](https://pipedream.com/docs/workflows/building-workflows/errors)
* [Pipedream concurrency and throttling](https://pipedream.com/docs/workflows/building-workflows/settings/concurrency-and-throttling)

## Next steps

* Read [API Reference](/api-reference/overview) for auth, rate limits, and errors.
* Read [Webhooks](/webhooks/overview) for payload shape and retries.
* Read [Extraction Workflow](/guides/extraction-workflow) for job creation and result pagination.
* Choose Make or Zapier when the team wants no-code scenario builders.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.