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

# Make.com Twitter integration for X API automation

> Build Make Twitter automation for tweet search, followers, scheduled posts, webhooks, and X API errors. Connect profiles, replies, and monitors through Make.

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

Xquik supports a Make.com Twitter integration without an X Developer app.

Build tweet searches, profile lookups, follower exports, scheduled posts, and monitor alerts.
The same integration supports replies, trends, extraction jobs, and signed webhooks.

The 2025 decommissioning removed Make's native X app.
A private Make custom app keeps each scenario focused and authentication testable.
Teams can later decide whether public app review fits their distribution needs.

## Choose a Make Twitter automation pattern

A Make Twitter automation should start with one clear trigger.
Use schedules for recurring tweet searches, trends, or follower exports.
Instant webhook delivery applies to replies, quotes, reposts, and new tweets.
Use polling when an extraction job can finish after the scenario ends.

Build a Make scenario automation around one bounded Xquik operation.
Then route normalized tweet or profile fields to each destination.
This structure keeps the automation workflow observable and easier to retry.

The HTTP module supports a limited private prototype.
A private custom app suits reusable actions and consistent error handling.
Both approaches can call the same documented API endpoints.

## Build a Make.com API integration

A Make.com API integration uses an Xquik API key for authentication.
It does not require X OAuth or a native Twitter account connection.
The Make custom app stores the key inside an encrypted connection field.

Use `/account` to validate API keys without changing tweets or profiles.
Place the base URL, authentication header, and sanitization rules centrally.
Focused modules should cover tweets, users, followers, monitors, and webhooks.

A Make Twitter integration should return small, stable output bundles.
Avoid passing complete API responses into Slack, Sheets, or a CRM.
The Make API integration should retain IDs, cursors, timestamps, and status fields.

Treat the Make Twitter API layer as a private integration boundary.
The integration platform can then support drag-and-drop scenario assembly.
This step-by-step structure keeps every module focused on one result.

## Prerequisites

* [Xquik API key](/x-api-quickstart)
* Make organization with Custom Apps access
* HTTPS Make webhook URL for instant monitor-event scenarios
* Optional Slack, Sheets, Airtable, or CRM module for downstream steps

## App shape

<CardGroup cols={2}>
  <Card title="Connection" icon="key-round">
    Use an API key parameter named `apiKey` and inject it as `x-api-key`.
  </Card>

  <Card title="Base URL" icon="link">
    Call Xquik REST modules from `https://xquik.com/api/v1`.
  </Card>

  <Card title="Modules" icon="boxes">
    Start with Search Tweets, Get Tweet, Get User, Get Trends, Create Tweet, Create Extraction, Create Monitor, Create Webhook, and Make an API Call.
  </Card>

  <Card title="Triggers" icon="radio">
    Support Monitor Event instant webhooks and Extraction Completed polling.
  </Card>

  <Card title="Error handling" icon="circle-alert">
    Map `401`, `402`, `429`, and `5xx` to short scenario messages.
  </Card>
</CardGroup>

Make custom apps split this into a connection, base request settings, modules, and optional webhook components. Use Xquik's `/account` endpoint as the connection test because it validates the API key without mutating data.

## Connection

Create a connection parameter that stores the API key as a password field:

```json theme={null}
[
  {
    "name": "apiKey",
    "label": "Xquik API Key",
    "type": "password",
    "required": true,
    "editable": true,
    "help": "Create an API key in the Xquik dashboard."
  }
]
```

Use `GET /account` to validate the connection:

```json theme={null}
{
  "url": "https://xquik.com/api/v1/account",
  "method": "GET",
  "headers": {
    "x-api-key": "{{parameters.apiKey}}"
  },
  "response": {
    "metadata": {
      "type": "email",
      "value": "{{body.email}}"
    },
    "error": {
      "message": "{{body.message || body.error || 'Xquik authentication failed.'}}"
    }
  },
  "log": {
    "sanitize": ["request.headers.x-api-key"]
  }
}
```

## Base request pattern

Use one base request pattern for JSON modules:

```json theme={null}
{
  "baseUrl": "https://xquik.com/api/v1",
  "headers": {
    "x-api-key": "{{connection.apiKey}}",
    "content-type": "application/json"
  },
  "response": {
    "error": {
      "message": "{{body.message || body.error || 'Xquik request failed.'}}"
    }
  },
  "log": {
    "sanitize": ["request.headers.x-api-key"]
  }
}
```

Handle status codes consistently:

<CardGroup cols={2}>
  <Card title="401 authentication" icon="key-round">
    Authentication failed. Check the Xquik API key.
  </Card>

  <Card title="402 billing state" icon="credit-card">
    Subscription or credits required. Update billing in Xquik.
  </Card>

  <Card title="429 rate limit" icon="timer">
    Rate limited. Respect the `Retry-After` header before retrying.
  </Card>

  <Card title="5xx transient" icon="refresh-cw">
    Xquik service unavailable. Retry with exponential backoff.
  </Card>
</CardGroup>

## Control rate limiting and error handling

Read each endpoint contract before configuring retries.
Xquik documents status codes per route, not as universal responses.

* A `400` response means invalid request fields. Correct the module mapping first.
* A `401` response means invalid authentication. Replace the API key.
* A `402` response means a billing requirement. Add credits or update the subscription first.
* A `404` response means a missing tweet, profile, monitor, or webhook.
* A `424` response means a dependency failure. Retry safe reads with bounded backoff.
* A `429` response means rate limiting. Wait for the `Retry-After` header before retrying.
* A `502` response means a temporary upstream failure. Retry safe reads after a capped backoff.

Never retry a write only because its HTTP status appears temporary.
Inspect the returned `safeToRetry` field for every write action.
Use a new idempotency key only when the contract permits another attempt.

Make webhooks can queue bursts before a scenario processes them.
Set a scenario rate limit that matches the destination's capacity.
Enable sequential processing when bundle order matters.
Use incomplete executions for recoverable failures that need operator review.

## Starter modules

<CardGroup cols={3}>
  <Card title="Search tweets" icon="search">
    Search module. Call `GET /x/tweets/search` with `q`. Use `cursor` for page loops and keep `limit` on bounded resumes.
  </Card>

  <Card title="Get tweet" icon="message-circle">
    Action module. Call `GET /x/tweets/{id}` with a tweet ID.
  </Card>

  <Card title="Get user" icon="user-round">
    Action module. Call `GET /x/users/{id}` with a user ID or username.
  </Card>

  <Card title="Get trends" icon="trending-up">
    Search module. Call `GET /x/trends` with optional `woeid` and `count`.
  </Card>

  <Card title="Create tweet" icon="send">
    Action module. Call `POST /x/tweets` with account, text, and optional public media URLs.
  </Card>

  <Card title="Create extraction" icon="boxes">
    Action module. Call `POST /extractions` with `toolType`, query fields, and result limit.
  </Card>

  <Card title="Create monitor" icon="radio">
    Action module. Call `POST /monitors` with username and event types.
  </Card>

  <Card title="Create webhook" icon="webhook">
    Action module. Call `POST /webhooks` with callback URL and event types.
  </Card>

  <Card title="Make an API call" icon="terminal">
    Universal module. Accept any `/api/v1` path for endpoints that have no module yet.
  </Card>
</CardGroup>

Example Search Tweets module communication:

```json theme={null}
{
  "url": "/x/tweets/search",
  "method": "GET",
  "qs": {
    "q": "{{parameters.q}}",
    "cursor": "{{parameters.cursor}}"
  },
  "response": {
    "iterate": "{{body.tweets}}",
    "output": {
      "id": "{{item.id}}",
      "text": "{{item.text}}",
      "authorUsername": "{{item.author.username}}",
      "url": "{{item.url}}"
    }
  }
}
```

Add a bounded-pull variant that sends `limit`. If `body.has_next_page` is `true`, send `body.next_cursor` as `cursor` with the same `q`, filters, and `limit`.

## Output handoff

Make response handling lets search modules `iterate` over `body.tweets` while `body` stays available for output, wrapper, and pagination fields. Emit tweet bundles from `item`, then carry setup IDs, write status, and page cursors in scenario state when downstream modules need another request. Use snake\_case keys for data-store rows even when the API response uses camelCase.

<CardGroup cols={2}>
  <Card title="Tweet search page" icon="search">
    Store `q`, each `tweet_id`, `text`, `author_username`, `created_at`, `has_next_page`, and `next_cursor`.
  </Card>

  <Card title="User profile rows" icon="users">
    Store source `id` as `user_id`, plus `username`, `name`, `followers`, `verified`, and `profile_picture`. For user-list modules, carry `has_next_page` and `next_cursor`.
  </Card>

  <Card title="Trend rows" icon="trending-up">
    Store each trend `name`, `rank`, `query`, and `description`. Keep `body.count`, `body.woeid`, and the selected region in scenario state.
  </Card>

  <Card title="Tweet or reply write" icon="send">
    Send a unique `Idempotency-Key`. Store the returned action. Poll `status_url` while `terminal` is false. Retry only when `safe_to_retry` is true, using a new key.
  </Card>

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

  <Card title="Monitor and webhook setup" icon="radio">
    Store monitor `id`, `username`, `xUserId`, `eventTypes`, `isActive`, `nextBillingAt`, webhook `id`, `url`, `eventTypes`, and the one-time `secret`. For Make storage rows, 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="Extraction jobs" icon="database">
    Store `id`, `tool_type`, and `status` from `POST /extractions`. Poll `GET /extractions/{id}`, then carry `has_more` and `next_cursor`.
  </Card>

  <Card title="Webhook event deduplication" icon="fingerprint">
    Store `deliveryId` for endpoint-level retry deduplication and `streamEventId` when one monitor event must process once across receiver changes.
  </Card>

  <Card title="Stored event replay" icon="activity">
    Call `GET /api/v1/events` with `cursor` when a scenario needs replay. Map `id`, `monitorId`, `monitorType`, `occurredAt`, `hasMore`, and `nextCursor` to `event_id`, `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 scenario logs, data stores, Slack messages, CRM rows, and retry queues.
  </Card>
</CardGroup>

## Instant trigger: monitor events

Use a dedicated Make webhook for monitor events. Register that webhook URL in Xquik:

```json theme={null}
{
  "url": "https://xquik.com/api/v1/webhooks",
  "method": "POST",
  "body": {
    "url": "{{webhook.url}}",
    "eventTypes": ["tweet.new", "tweet.reply", "tweet.quote", "tweet.retweet"]
  }
}
```

Then create or confirm the monitor:

```json theme={null}
{
  "url": "https://xquik.com/api/v1/monitors",
  "method": "POST",
  "body": {
    "username": "username",
    "eventTypes": ["tweet.new", "tweet.reply", "tweet.quote", "tweet.retweet"]
  }
}
```

Map webhook output fields for downstream modules:

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

  <Card title="Delivery ID" icon="fingerprint">
    Map `deliveryId` as the per-endpoint idempotency key for retries.
  </Card>

  <Card title="Stream event ID" icon="link">
    Map `streamEventId` when one monitor event should process once across endpoint changes.
  </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. If the scenario includes a verification step before routing, verify `x-xquik-signature` with that secret before sending alerts.

## Polling trigger: extraction completed

Use a polling trigger when users want bulk results without webhook setup:

```json theme={null}
{
  "url": "/extractions",
  "method": "GET",
  "qs": {
    "status": "completed",
    "limit": 25
  },
  "response": {
    "iterate": "{{body.extractions}}",
    "uid": "{{item.id}}",
    "output": {
      "id": "{{item.id}}",
      "status": "{{item.status}}",
      "toolType": "{{item.toolType}}",
      "createdAt": "{{item.createdAt}}",
      "completedAt": "{{item.completedAt}}"
    }
  }
}
```

Fetch the job detail with `GET /extractions/{id}` and loop through `nextCursor` when `hasMore` is true.

## Recipes

### Social listening to Slack

<CardGroup cols={2}>
  <Card title="Monitor event trigger" icon="radio">
    Start from the Xquik Monitor Event instant trigger for `tweet.new`, `tweet.reply`, `tweet.quote`, and `tweet.retweet`.
  </Card>

  <Card title="Topic filter" icon="funnel">
    Filter on `eventType`, `username`, and `data.text` before routing alerts.
  </Card>

  <Card title="Slack message" icon="message-square">
    Create a Slack message from `data.text`, `data.id`, `data.author.userName`, and `occurredAt`.
  </Card>

  <Card title="Deduplication store" icon="database">
    Upsert by `deliveryId` per endpoint. Use `streamEventId` when one monitor event should fan out once across endpoint changes.
  </Card>
</CardGroup>

### Daily topic research to sheets

<CardGroup cols={2}>
  <Card title="Schedule trigger" icon="calendar-clock">
    Run the scenario on a daily schedule for repeatable topic research.
  </Card>

  <Card title="Search tweets" icon="search">
    Call Xquik Search Tweets with `q`. Use `cursor` for page loops and keep `limit` on bounded resumes.
  </Card>

  <Card title="Iterator" icon="list">
    Iterate over `tweets` and pass one tweet bundle to each downstream module.
  </Card>

  <Card title="Sheet row" icon="table">
    Append `id`, `author.username`, `text`, `createdAt`, `likeCount`, and `retweetCount`.
  </Card>
</CardGroup>

### Bulk extraction to CRM

<CardGroup cols={3}>
  <Card title="Start run" icon="play">
    Use a scheduler or manual trigger to start the bulk extraction.
  </Card>

  <Card title="Create extraction" icon="boxes">
    Call Xquik Create Extraction with `toolType` and the required target fields.
  </Card>

  <Card title="Wait or poll" icon="timer">
    Wait before polling, or reuse the Extraction Completed polling trigger.
  </Card>

  <Card title="Get extraction" icon="search">
    Call `GET /extractions/{id}` until `job.status` is `completed` or `failed`.
  </Card>

  <Card title="CRM upsert" icon="database">
    Upsert by user `id`, then follow `hasMore` and `nextCursor` for additional result pages.
  </Card>
</CardGroup>

## Automate focused Twitter workflows

Tweet search automation can collect posts matching a brand or topic query.
Filter by author, timestamp, language, or engagement before sending alerts.
Store tweet IDs so repeated searches do not create duplicate messages.

A Twitter monitor webhook can route new tweets and replies right away.
Verify its signature before parsing the request body.
Deduplicate deliveries before posting to Slack or updating a CRM.

Use follower pages for bounded exports to Google Sheets.
Use extraction jobs for larger follower or following exports.
Keep profile IDs because usernames can change.

Social media automation should keep publishing under human control.
Send every scheduled tweet and reply through an approval queue.
Review text, links, media, and the target account before posting tweets.
Do not automate unsolicited replies, follows, or direct messages.

## Make.com Twitter integration questions

### How do I connect the Twitter API to Make?

Use a private Make custom app or the HTTP module.
Authenticate each Xquik request with the `x-api-key` header.
Start with one read endpoint before adding writes or webhooks.

### Does Make.com still have a native Twitter integration?

The native X app became unavailable in Make during 2025.
Xquik remains available through a private app or the Make HTTP module.
This approach avoids a native Twitter integration dependency.

### How can I schedule tweets automatically?

Create a scheduled scenario that prepares one draft payload.
Send the draft through an approval step before publishing.
Use an idempotency key and inspect the returned write status.

### How do I build a Twitter webhook in Make?

Register a Make webhook URL with Xquik.
Choose the required monitor event types during webhook registration.
Verify signatures, reject stale requests, and deduplicate event IDs.

### Can Make automate Twitter search without coding?

Yes. Install the private Xquik app, then configure its search module.
Map the query, filters, limit, and cursor through the scenario builder.
The scenario can append matching tweets to Sheets without custom code.

### How do I automate replies based on keywords?

Search recent replies or receive monitored account events.
Filter each tweet with explicit terms and safety rules.
Send the proposed reply to an approval queue before publishing.

### How do I connect Twitter activity to a CRM?

Receive a verified monitor event, then fetch its author profile.
Upsert the CRM record by the immutable X user ID.
Keep the triggering tweet URL with the profile fields.

### Which Twitter automation tool fits Make scenarios?

Use Xquik when scenarios need tweets, profiles, followers, or monitor webhooks.
Use Make for scheduling, routing, approvals, and destination integrations.
Together, they form a focused Twitter API integration.

## Make and Xquik sources

* [Make custom app base configuration](https://developers.make.com/custom-apps-documentation/app-components/base)
* [Make connection validation guidance](https://developers.make.com/custom-apps-documentation/best-practices/connections)
* [Make community decommissioning notice](https://community.make.com/t/make-is-officially-decommissioning-x-formerly-twitter-app/77497)
* [Make webhook documentation](https://help.make.com/webhooks)
* [Make scenario scheduling](https://help.make.com/schedule-a-scenario)
* [Xquik webhook verification](/webhooks/overview)

## Test checklist

* Connection test rejects invalid API keys with a clear `401` message.
* Every module sanitizes `x-api-key` in logs.
* Search modules return arrays and stable IDs for Make deduplication.
* The instant trigger must map `tweet.new`, `tweet.reply`, `tweet.quote`, and `tweet.retweet`.
* Extraction polling stops when the API returns no new completed jobs.
* A `429` test confirms that retry timing follows `Retry-After`.
* The Universal module accepts any `/api/v1` path but still injects the API key.

## Next steps

* Read [Webhooks](/webhooks/overview) for payload shape and retries.
* Read [Extraction Workflow](/guides/extraction-workflow) for job creation and pagination.
* Use [Zapier](/guides/zapier) or [Pipedream](/guides/pipedream) when the team prefers code-backed workflow components.


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