Every API here is available over the APIs.io API and to AI agents over MCP.
MCP server
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
Tools for apis
7 MCP tools reach this
find_apisBrowse and filter every API in the catalog.
get_api_artifactsOne API's artifacts, grouped by type.
get_openapiThe primary OpenAPI for this API.
find_similar_apisAPIs that look like this one.
apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
resolveTurn a domain, URL or GitHub org into the provider it belongs to.
find_cohortsEvery scored population of providers in the catalog.
All 92 tools →
Call it yourself
curl for this page
This API
curl "https://apis.io/api/v1/apis/xquik-api-composition-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"
Discovery needs no key. Ratings and market analysis are Pro.
Get an API key
Free tier, no email required.
A second provider on the same verified email joins the account you already have.
openapi: 3.2.0
info:
title: Xquik Composition API
version: '1.0'
description: "Xquik is an independent third-party service. Not affiliated with X Corp. \"Twitter\" and \"X\" are trademarks of X Corp. Look up tweets, users, and X trends. Search tweets, check follow relationships, download media, and monitor accounts. 33 paid-read endpoints accept prepaid credits without a subscription. 7 fixed-price lookups also accept direct MPP payments. Write and automation endpoints require an API key or OAuth 2.1 bearer token.\n\n## Xquik SDKs\n\nStainless generates each SDK from this OpenAPI schema. Pick a language:\n\n- TypeScript / Node.js: `npm i x-twitter-scraper` -\n [Xquik-dev/x-twitter-scraper-typescript](https://github.com/Xquik-dev/x-twitter-scraper-typescript)\n\n- Python: `pip install x-twitter-scraper` -\n [Xquik-dev/x-twitter-scraper-python](https://github.com/Xquik-dev/x-twitter-scraper-python)\n\n- Go: `go get github.com/Xquik-dev/x-twitter-scraper-go` -\n [Xquik-dev/x-twitter-scraper-go](https://github.com/Xquik-dev/x-twitter-scraper-go)\n\n- Ruby: `gem install x-twitter-scraper` -\n [Xquik-dev/x-twitter-scraper-ruby](https://github.com/Xquik-dev/x-twitter-scraper-ruby)\n\n- Java (source build; Maven Central pending) -\n [Xquik-dev/x-twitter-scraper-java](https://github.com/Xquik-dev/x-twitter-scraper-java)\n\n- Kotlin (source build; Maven Central pending) -\n [Xquik-dev/x-twitter-scraper-kotlin](https://github.com/Xquik-dev/x-twitter-scraper-kotlin)\n\n- C# / .NET: `dotnet add package XTwitterScraper` -\n [Xquik-dev/x-twitter-scraper-csharp](https://github.com/Xquik-dev/x-twitter-scraper-csharp)\n\n- PHP: `composer require xquik/x-twitter-scraper` -\n [Xquik-dev/x-twitter-scraper-php](https://github.com/Xquik-dev/x-twitter-scraper-php)\n\n- CLI: `go install github.com/Xquik-dev/x-twitter-scraper-cli/cmd/x-twitter-scraper@latest` -\n [Xquik-dev/x-twitter-scraper-cli](https://github.com/Xquik-dev/x-twitter-scraper-cli)\n\n- Terraform Provider (Terraform Registry) -\n [Xquik-dev/terraform-provider-x-twitter-scraper](https://github.com/Xquik-dev/terraform-provider-x-twitter-scraper)\n\n\nOpenClaw plugin: [Xquik-dev/tweetclaw](https://github.com/Xquik-dev/tweetclaw) (`openclaw plugins install clawhub:@xquik/tweetclaw`)."
x-guidance: '## Common tasks
**Find a tweet** - GET /x/tweets/{id} with a numeric tweet ID. Returns full tweet data: text, author, metrics (likes, retweets, replies, views), media URLs, and creation timestamp. Cost: $0.00015 per lookup.
**Search tweets** - GET /x/tweets/search?q={query}&limit={n}. Supports X search operators, structured filters like fromUser, mediaType, minFaves, hashtags, and verifiedOnly, plus exact lookup for a pasted Tweet ID or X status URL. Plain from:user date windows are optimized for timeline completeness. Returns up to 200 tweets per page with cursor-based pagination. Cost: $0.00015 per tweet returned.
**Find a user** - GET /x/users/{id} where {id} is a numeric user ID or @username. Returns profile data: name, bio, follower/following counts, verification status, join date. Cost: $0.00015 per lookup.
**Check if A follows B** - GET /x/followers/check?source={a}&target={b} where source and target are usernames, @usernames, or X or Twitter profile URLs. Cost: $0.00075.
**Get trending topics** - GET /trends?woeid={region}&count={n}. WOEID 1 = worldwide, 23424977 = US, 23424975 = UK, 23424969 = Turkey. Cost: $0.00045.
**Download media** - POST /x/media/download with {"tweetIds": ["123", "456"]} body. Returns download URLs for images and videos. Cost: 1 credit per fresh tweet processed with media; cached repeat downloads are free.
**Read an article** - GET /x/articles/{tweetId} for long-form X Articles. Returns full article HTML, cover image, and metadata. Cost: $0.00075.
## Pagination
Default v1 responses keep their existing pagination fields for compatibility. Platform list endpoints return `hasMore` and `nextCursor`; X data endpoints return `has_next_page` and `next_cursor`. Send `xquik-api-contract: 2026-04-29` to receive the unified best-practice fields `has_more` and `next_cursor`. Pass the cursor back as `?cursor={cursor}`; legacy `?after={cursor}` still works. Dynamic-priced endpoints charge per item returned, not per request.
## Authentication
Eligible paid read endpoints accept accountless prepaid credit wallets. Fixed-price lookups also accept direct MPP payments. Media downloads, write endpoints, and automation features require authentication. Send an Xquik API key through `x-api-key`, `Xquik-Api-Key`, or `Authorization: Bearer xq_...`. Send an OAuth 2.1 access token through `Authorization: Bearer`.
## Best-Practice Response Contract
v1 keeps its original response contract by default so existing integrations do not break. Send `xquik-api-contract: 2026-04-29` to opt in to the best-practice contract: snake_case response fields, Unix timestamps in seconds, structured error objects, `has_more` and `next_cursor` pagination fields, `object` resource identifiers, and prefixed IDs where available. Dependency failures that returned 502 in default v1 return 424 in the opt-in contract. Future major API versions should make this contract the default.'
contact:
name: Xquik
url: https://xquik.com
email: support@xquik.com
servers:
- url: https://xquik.com
security:
- apiKey: []
- oauthBearer: []
tags:
- name: Composition
description: AI tweet composition, drafts, writing styles, and radar
paths:
/api/v1/compose:
post:
operationId: compose
summary: Build, refine, or check a post draft
description: 'Run one step of Xquik''s three-step writing workflow. Compose returns questions, editorial rules, and source-specific Radar recommendations. Refine returns goal-specific guidance. Score applies deterministic text checks. It does not predict reach or expose X ranking weights.
'
tags:
- Composition
security:
- apiKey: []
- oauthBearer: []
requestBody:
required: true
description: Send exactly one workflow step and its required fields.
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/ComposePrepareRequest'
- $ref: '#/components/schemas/ComposeRefineRequest'
- $ref: '#/components/schemas/ComposeScoreRequest'
example:
step: compose
topic: PostgreSQL query planning
goal: engagement
responses:
'200':
description: Result for the requested workflow step
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/ComposePrepareResult'
- $ref: '#/components/schemas/ComposeRefineResult'
- $ref: '#/components/schemas/ComposeScoreResult'
example:
checklist:
- factor: No external links in body
passed: true
- factor: No hashtags
passed: true
- factor: No excessive capitalization
passed: true
- factor: Length between 50 and 280 characters
passed: true
- factor: No excessive punctuation
passed: true
- factor: No emojis
passed: true
- factor: No em dashes or double dashes
passed: true
- factor: Sufficient substance
passed: true
- factor: Link-in-reply strategy
passed: true
nextStep: 'All 9 checks passed. Get an account from GET /api/v1/x/accounts. Then send the draft to POST /api/v1/x/tweets. The intentUrl also supports one-click posting.
'
passed: true
passedCount: 9
topSuggestion: All Xquik editorial checks passed.
totalChecks: 9
intentUrl: https://x.com/intent/tweet?text=PostgreSQL%2018%20reduced%20query%20latency
'400':
$ref: '#/components/responses/InvalidInput'
'401':
$ref: '#/components/responses/Unauthenticated'
'429':
$ref: '#/components/responses/RateLimitExceeded'
default:
content:
application/json:
example:
error: internal_error
message: Unexpected error. Try again.
schema:
$ref: '#/components/schemas/Error'
description: Unexpected error.
/api/v1/drafts:
get:
operationId: listDrafts
summary: List saved drafts
tags:
- Composition
security:
- apiKey: []
- oauthBearer: []
parameters:
- $ref: '#/components/parameters/Limit'
- name: afterCursor
in: query
schema:
type: string
description: Cursor for pagination
responses:
'200':
description: Draft list
content:
application/json:
schema:
type: object
required:
- drafts
- hasMore
properties:
drafts:
type: array
items:
$ref: '#/components/schemas/Draft'
example: []
hasMore:
type: boolean
example: false
nextCursor:
type: string
example: abc123
example:
drafts: []
hasMore: false
'401':
$ref: '#/components/responses/Unauthenticated'
'429':
$ref: '#/components/responses/RateLimitExceeded'
default:
content:
application/json:
example:
error: internal_error
message: Unexpected error. Try again.
schema:
$ref: '#/components/schemas/Error'
description: Unexpected error.
description: List saved drafts.
post:
operationId: createDraft
summary: Save a tweet draft
tags:
- Composition
security:
- apiKey: []
- oauthBearer: []
requestBody:
required: true
description: Draft text with optional topic and optimization goal.
content:
application/json:
schema:
type: object
required:
- text
properties:
text:
type: string
example: AI is the future of productivity
topic:
type: string
example: AI trends
goal:
type: string
enum:
- engagement
- followers
- authority
- conversation
example: engagement
example:
text: AI is the future of productivity
topic: AI trends
goal: engagement
responses:
'201':
description: Draft created
content:
application/json:
schema:
$ref: '#/components/schemas/DraftDetail'
example:
id: '42'
text: AI is the future of productivity
topic: AI trends
goal: engagement
createdAt: '2025-01-15T12:00:00Z'
updatedAt: '2025-01-16T09:30:00Z'
'400':
$ref: '#/components/responses/InvalidInput'
'401':
$ref: '#/components/responses/Unauthenticated'
'429':
$ref: '#/components/responses/RateLimitExceeded'
default:
content:
application/json:
example:
error: internal_error
message: Unexpected error. Try again.
schema:
$ref: '#/components/schemas/Error'
description: Unexpected error.
description: Save a tweet draft.
/api/v1/drafts/{id}:
get:
operationId: getDraft
summary: Get draft by ID
tags:
- Composition
security:
- apiKey: []
- oauthBearer: []
parameters:
- $ref: '#/components/parameters/ResourceId'
responses:
'200':
description: Draft details
content:
application/json:
schema:
$ref: '#/components/schemas/DraftDetail'
example:
id: '42'
text: AI is the future of productivity
topic: AI trends
goal: engagement
createdAt: '2025-01-15T12:00:00Z'
updatedAt: '2025-01-16T09:30:00Z'
'400':
$ref: '#/components/responses/InvalidInput'
'401':
$ref: '#/components/responses/Unauthenticated'
'404':
$ref: '#/components/responses/NotFound'
'429':
$ref: '#/components/responses/RateLimitExceeded'
default:
content:
application/json:
example:
error: internal_error
message: Unexpected error. Try again.
schema:
$ref: '#/components/schemas/Error'
description: Unexpected error.
description: Get draft by ID.
delete:
operationId: deleteDraft
summary: Delete a draft
tags:
- Composition
security:
- apiKey: []
- oauthBearer: []
parameters:
- $ref: '#/components/parameters/ResourceId'
responses:
'204':
$ref: '#/components/responses/NoContent'
'400':
$ref: '#/components/responses/InvalidInput'
'401':
$ref: '#/components/responses/Unauthenticated'
'404':
$ref: '#/components/responses/NotFound'
'429':
$ref: '#/components/responses/RateLimitExceeded'
default:
content:
application/json:
example:
error: internal_error
message: Unexpected error. Try again.
schema:
$ref: '#/components/schemas/Error'
description: Unexpected error.
description: Delete a draft.
/api/v1/styles:
get:
operationId: listStyles
summary: List cached style profiles
tags:
- Composition
security:
- apiKey: []
- oauthBearer: []
responses:
'200':
description: Style profile list
content:
application/json:
schema:
type: object
required:
- styles
properties:
styles:
type: array
items:
$ref: '#/components/schemas/StyleProfileSummary'
example: []
example:
styles: []
'401':
$ref: '#/components/responses/Unauthenticated'
'429':
$ref: '#/components/responses/RateLimitExceeded'
default:
content:
application/json:
example:
error: internal_error
message: Unexpected error. Try again.
schema:
$ref: '#/components/schemas/Error'
description: Unexpected error.
description: List cached style profiles.
post:
operationId: analyzeStyle
summary: Analyze writing style from recent tweets
tags:
- Composition
security:
- apiKey: []
- oauthBearer: []
requestBody:
required: true
description: X username whose recent tweets define the style.
content:
application/json:
schema:
type: object
required:
- username
properties:
username:
type: string
description: X username to analyze
example: elonmusk
example:
username: elonmusk
responses:
'200':
description: Fresh cached style profile returned
content:
application/json:
schema:
$ref: '#/components/schemas/StyleProfile'
example:
xUsername: elonmusk
tweetCount: 50
isOwnAccount: true
fetchedAt: '2025-01-15T12:00:00Z'
tweets:
- id: '1234567890'
text: Just launched our new feature!
'201':
description: Style profile created or refreshed
content:
application/json:
schema:
$ref: '#/components/schemas/StyleProfile'
example:
xUsername: elonmusk
tweetCount: 50
isOwnAccount: true
fetchedAt: '2025-01-15T12:00:00Z'
tweets:
- id: '1234567890'
text: Just launched our new feature!
'400':
$ref: '#/components/responses/InvalidInput'
'401':
$ref: '#/components/responses/Unauthenticated'
'402':
$ref: '#/components/responses/PaymentRequired'
'429':
$ref: '#/components/responses/RateLimitExceeded'
default:
content:
application/json:
example:
error: internal_error
message: Unexpected error. Try again.
schema:
$ref: '#/components/schemas/Error'
description: Unexpected error.
description: Analyze writing style from recent tweets.
/api/v1/styles/compare:
get:
operationId: compareStyles
summary: Compare two style profiles
tags:
- Composition
security:
- apiKey: []
- oauthBearer: []
parameters:
- name: username1
in: query
required: true
schema:
type: string
description: First username to compare
- name: username2
in: query
required: true
schema:
type: string
description: Second username to compare
responses:
'200':
description: Style comparison
content:
application/json:
schema:
type: object
required:
- style1
- style2
properties:
style1:
$ref: '#/components/schemas/StyleProfile'
style2:
$ref: '#/components/schemas/StyleProfile'
example:
style1:
xUsername: elonmusk
tweetCount: 50
isOwnAccount: true
fetchedAt: '2025-01-15T12:00:00Z'
tweets:
- id: '1234567890'
text: Just launched our new feature!
style2:
xUsername: BillGates
tweetCount: 40
isOwnAccount: false
fetchedAt: '2025-01-15T12:00:00Z'
tweets:
- id: '9876543210'
text: Climate change is a global challenge.
'400':
$ref: '#/components/responses/InvalidInput'
'401':
$ref: '#/components/responses/Unauthenticated'
'404':
$ref: '#/components/responses/NotFound'
'429':
$ref: '#/components/responses/RateLimitExceeded'
default:
content:
application/json:
example:
error: internal_error
message: Unexpected error. Try again.
schema:
$ref: '#/components/schemas/Error'
description: Unexpected error.
description: Compare two style profiles.
/api/v1/styles/{id}:
get:
operationId: getStyle
summary: Get cached style profile
tags:
- Composition
security:
- apiKey: []
- oauthBearer: []
parameters:
- $ref: '#/components/parameters/StyleId'
responses:
'200':
description: Style profile
content:
application/json:
schema:
$ref: '#/components/schemas/StyleProfile'
example:
xUsername: elonmusk
tweetCount: 50
isOwnAccount: true
fetchedAt: '2025-01-15T12:00:00Z'
tweets:
- id: '1234567890'
text: Just launched our new feature!
'401':
$ref: '#/components/responses/Unauthenticated'
'404':
$ref: '#/components/responses/NotFound'
'429':
$ref: '#/components/responses/RateLimitExceeded'
default:
content:
application/json:
example:
error: internal_error
message: Unexpected error. Try again.
schema:
$ref: '#/components/schemas/Error'
description: Unexpected error.
description: Get cached style profile.
put:
operationId: saveStyle
summary: Save style profile with custom tweets
tags:
- Composition
security:
- apiKey: []
- oauthBearer: []
parameters:
- $ref: '#/components/parameters/StyleId'
requestBody:
required: true
description: Label and sample tweets that define the style profile.
content:
application/json:
schema:
type: object
required:
- label
- tweets
properties:
label:
type: string
description: Display label for the style
example: Professional Voice
tweets:
type: array
items:
type: object
required:
- text
properties:
text:
type: string
example: Excited to share our latest research findings.
description: Array of tweet objects
example:
- text: Excited to share our latest research findings.
example:
label: Professional Voice
tweets:
- text: Excited to share our latest research findings.
responses:
'200':
description: Style profile saved
content:
application/json:
schema:
$ref: '#/components/schemas/StyleProfile'
example:
xUsername: elonmusk
tweetCount: 1
isOwnAccount: true
fetchedAt: '2025-01-15T12:00:00Z'
tweets:
- id: '1234567890'
text: Excited to share our latest research findings.
'400':
$ref: '#/components/responses/InvalidInput'
'401':
$ref: '#/components/responses/Unauthenticated'
'429':
$ref: '#/components/responses/RateLimitExceeded'
default:
content:
application/json:
example:
error: internal_error
message: Unexpected error. Try again.
schema:
$ref: '#/components/schemas/Error'
description: Unexpected error.
description: Save style profile with custom tweets.
delete:
operationId: deleteStyle
summary: Delete a style profile
tags:
- Composition
security:
- apiKey: []
- oauthBearer: []
parameters:
- $ref: '#/components/parameters/StyleId'
responses:
'204':
$ref: '#/components/responses/NoContent'
'401':
$ref: '#/components/responses/Unauthenticated'
'404':
$ref: '#/components/responses/NotFound'
'429':
$ref: '#/components/responses/RateLimitExceeded'
default:
content:
application/json:
example:
error: internal_error
message: Unexpected error. Try again.
schema:
$ref: '#/components/schemas/Error'
description: Unexpected error.
description: Delete a style profile.
/api/v1/styles/{id}/performance:
get:
operationId: getStylePerformance
summary: Get engagement metrics for style tweets
tags:
- Composition
security:
- apiKey: []
- oauthBearer: []
parameters:
- $ref: '#/components/parameters/StyleId'
responses:
'200':
description: Performance metrics
content:
application/json:
schema:
type: object
required:
- xUsername
- tweetCount
- tweets
properties:
xUsername:
type: string
example: elonmusk
tweetCount:
type: integer
example: 5
tweets:
type: array
items:
type: object
required:
- id
- text
properties:
id:
type: string
example: '1234567890'
text:
type: string
example: Excited to share our latest research findings.
likeCount:
type: integer
example: 120
retweetCount:
type: integer
example: 15
replyCount:
type: integer
example: 8
viewCount:
type: integer
example: 5000
createdAt:
type: string
example: '2025-01-15T12:00:00Z'
example:
- id: '1234567890'
text: Excited to share our latest research findings.
likeCount: 120
retweetCount: 15
replyCount: 8
viewCount: 5000
createdAt: '2025-01-15T12:00:00Z'
example:
xUsername: elonmusk
tweetCount: 5
tweets:
- id: '1234567890'
text: Excited to share our latest research findings.
likeCount: 120
retweetCount: 15
replyCount: 8
viewCount: 5000
createdAt: '2025-01-15T12:00:00Z'
'401':
$ref: '#/components/responses/Unauthenticated'
'402':
$ref: '#/components/responses/PaymentRequired'
'404':
$ref: '#/components/responses/NotFound'
'429':
$ref: '#/components/responses/RateLimitExceeded'
default:
content:
application/json:
example:
error: internal_error
message: Unexpected error. Try again.
schema:
$ref: '#/components/schemas/Error'
description: Unexpected error.
description: Get engagement metrics for style tweets.
/api/v1/radar:
get:
operationId: getRadar
summary: Get trending topics from curated sources
tags:
- Composition
security:
- apiKey: []
- oauthBearer: []
parameters:
- name: after
in: query
schema:
type: string
description: Cursor for pagination (from prior response nextCursor).
- name: category
in: query
schema:
type: string
enum:
- general
- tech
- dev
- science
- culture
- politics
- business
- entertainment
description: Filter by category.
- name: hours
in: query
schema:
type: integer
minimum: 1
maximum: 72
default: 6
description: Lookback window in hours (1-72, default 6).
- name: limit
in: query
schema:
type: integer
minimum: 1
maximum: 100
default: 50
description: Number of items to return (1-100, default 50).
- name: region
in: query
schema:
type: string
default: global
description: Region filter. Use `global` or a region code such as `US`, `GB`, `TR`, or `ES`.
- name: source
in: query
schema:
type: string
enum:
- github
- google_trends
- hacker_news
- polymarket
- reddit
- trustmrr
- wikipedia
description: 'Source filter. One of: github, google_trends, hacker_news, polymarket, reddit, trustmrr, wikipedia'
responses:
'200':
description: Radar items
content:
application/json:
schema:
type: object
required:
- hasMore
- items
properties:
hasMore:
type: boolean
example: false
items:
type: array
items:
$ref: '#/components/schemas/RadarItem'
example: []
nextCursor:
type: string
description: Opaque cursor for the next page (present only when hasMore is true).
example: eyJ0IjoxNzM5OTcyODAwLCJpIjoiOTk5In0=
example:
hasMore: false
items: []
'400':
$ref: '#/components/responses/InvalidInput'
'401':
$ref: '#/components/responses/Unauthenticated'
'429':
$ref: '#/components/responses/RateLimitExceeded'
default:
content:
application/json:
example:
error: internal_error
message: Unexpected error. Try again.
schema:
$ref: '#/components/schemas/Error'
description: Unexpected error.
description: Get trending topics from curated sources.
components:
responses:
PaymentRequired:
description: 'Payment required. Fixed-price direct MPP requests return a Machine Payments Protocol problem document and a WWW-Authenticate challenge. Authenticated X data requests return balances and explicit Stripe checkout-creation actions. Guest paid-read keys receive only the accountless guest top-up action. Direct MPP challenges also advertise the Stripe wallet action. Other authenticated endpoints return a legacy error shape. A failed request never creates checkout. Create checkout only after the user confirms a payment option.
'
headers:
WWW-Authenticate:
description: MPP payment challenge for eligible anonymous pay-per-use requests. Authenticated credit or subscription errors omit this header.
schema:
type: string
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/XWritePaymentRequired'
- $ref: '#/components/schemas/AuthenticatedPaymentRequired'
- $ref: '#/components/schemas/GuestPaymentRequired'
- allOf:
- $ref: '#/components/schemas/Error'
- not:
required:
- payment_options
example:
balance: '0'
dashboard: /dashboard/account
error: insufficient_credits
message: Insufficient credits. Top up or subscribe to continue.
# --- truncated at 32 KB (85 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/xquik-api/refs/heads/main/openapi/xquik-api-composition-api-openapi.yml