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

# Twitter giveaway history API & past draw results

> List past Twitter giveaway draws with tweet URLs, statuses, entry counts, timestamps, and opaque cursors. Then retrieve winners or export audit records.

<Panel>
  <Tabs defaultTabIndex={0} sync={false}>
    <Tab title="200" id="response-draws-twitter-giveaway-history-200">
      ```json theme={null}
      {
        "draws": [],
        "hasMore": false
      }
      ```
    </Tab>

    <Tab title="400" id="response-draws-twitter-giveaway-history-400">
      ```json theme={null}
      {
        "error": "invalid_input",
        "message": "Invalid input. Check the request body."
      }
      ```
    </Tab>

    <Tab title="401" id="response-draws-twitter-giveaway-history-401">
      ```json theme={null}
      {
        "error": "unauthenticated",
        "message": "Authentication required. Provide a valid API key or bearer token."
      }
      ```
    </Tab>

    <Tab title="429" id="response-draws-twitter-giveaway-history-429">
      ```json theme={null}
      {
        "error": "rate_limit_exceeded",
        "message": "Too many requests. Try again later.",
        "retryAfter": 60
      }
      ```
    </Tab>
  </Tabs>
</Panel>

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

List every Twitter giveaway draw owned by the authenticated Xquik account.
Review source tweets, draw statuses, entry counts, and completion times.
Continue through older results with an opaque cursor.

This endpoint returns draw summaries. It does not return winner objects or
eligibility rules. Retrieve one draw when winner verification needs those
details.

<Callout icon="circle-check" color="#16a34a">
  **Free.** This endpoint does not consume credits.
</Callout>

## List past Twitter giveaway draws

Use `GET /draws` for a Twitter giveaway history page or audit queue. The API
orders results by `createdAt` and draw ID, newest first. Each row identifies its
source tweet and inspected candidate counts.

<CardGroup cols={2}>
  <Card title="List draw history" icon="history">
    Call `GET /draws` for draw IDs, tweet URLs, statuses, entry counts, and
    timestamps. Follow `nextCursor` when `hasMore` is true.
  </Card>

  <Card title="Review past winners" icon="trophy">
    Call `GET /draws/{id}` for source tweet metrics and ordered winner rows.
    Keep primary and backup winners separate.
  </Card>

  <Card title="Export audit records" icon="file-down">
    Call `GET /draws/{id}/export` for winners or entries. Choose CSV, JSON,
    Markdown, PDF, text, or XLSX.
  </Card>

  <Card title="Run another draw" icon="shuffle">
    Call `POST /draws` with the source tweet and eligibility rules. Do not reuse
    an old draw ID for a new selection.
  </Card>
</CardGroup>

Use list results to find draws. Use detail results to verify winners.
Use exports for review, customer support, or campaign archives.

<CodeGroup>
  ```bash cURL theme={null}
  curl --fail-with-body "https://xquik.com/api/v1/draws?limit=10" \
    -H "x-api-key: xq_YOUR_KEY_HERE" | jq
  ```

  ```javascript Node.js theme={null}
  const response = await fetch("https://xquik.com/api/v1/draws?limit=10", {
    headers: { "x-api-key": "xq_YOUR_KEY_HERE" },
  });
  const page = await response.json();
  if (!response.ok) {
    throw new Error(page.message || "Giveaway history request failed.");
  }

  const drawRows = page.draws.map((draw) => ({
    draw_id: draw.id,
    tweet_url: draw.tweetUrl,
    status: draw.status,
    total_entries: draw.totalEntries,
    valid_entries: draw.validEntries,
    created_at: draw.createdAt,
    drawn_at: draw.drawnAt || null,
  }));
  process.stdout.write(
    `${JSON.stringify({ drawRows, hasMore: page.hasMore, nextCursor: page.nextCursor || null })}\n`,
  );
  ```

  ```python Python theme={null}
  import requests

  response = requests.get(
      "https://xquik.com/api/v1/draws",
      headers={"x-api-key": "xq_YOUR_KEY_HERE"},
      params={"limit": 10},
  )
  response.raise_for_status()
  page = response.json()
  draw_rows = [
      {
          "draw_id": draw["id"],
          "tweet_url": draw["tweetUrl"],
          "status": draw["status"],
          "total_entries": draw["totalEntries"],
          "valid_entries": draw["validEntries"],
          "created_at": draw["createdAt"],
          "drawn_at": draw.get("drawnAt"),
      }
      for draw in page["draws"]
  ]
  print({"draws": draw_rows, "next_cursor": page.get("nextCursor")})
  ```

  ```go Go theme={null}
  package main

  import (
  	"fmt"
  	"io"
  	"log"
  	"net/http"
  )

  func main() {
  	req, err := http.NewRequest("GET", "https://xquik.com/api/v1/draws?limit=10", nil)
  	if err != nil {
  		log.Fatal(err)
  	}
  	req.Header.Set("x-api-key", "xq_YOUR_KEY_HERE")

  	resp, err := http.DefaultClient.Do(req)
  	if err != nil {
  		log.Fatal(err)
  	}
  	defer resp.Body.Close()

  	body, err := io.ReadAll(resp.Body)
  	if err != nil {
  		log.Fatal(err)
  	}
  	if resp.StatusCode < 200 || resp.StatusCode >= 300 {
  		log.Fatalf("giveaway history failed with %d: %s", resp.StatusCode, string(body))
  	}
  	fmt.Println(string(body))
  }
  ```
</CodeGroup>

## Choose the correct giveaway result

The list route answers which draws exist. It also shows when each draw ran.
It cannot answer who won or which reply qualified.

Use this handoff for each returned row:

<CardGroup cols={2}>
  <Card title="Find past draws" icon="list-filter">
    Call `GET /draws`. Keep `id`, `tweetUrl`, `status`, and `createdAt`.
  </Card>

  <Card title="Compare entry counts" icon="list-checks">
    Read `totalEntries` and `validEntries` from each list summary.
  </Card>

  <Card title="Verify winners" icon="badge-check">
    Call `GET /draws/{id}`. Keep position, username, tweet ID, and backup
    state.
  </Card>

  <Card title="Review the source tweet" icon="message-square-text">
    Read the tweet ID, text, author, and engagement counts from draw detail.
  </Card>

  <Card title="Download results" icon="download">
    Call `GET /draws/{id}/export`. Select `winners` or `entries` and one format.
  </Card>
</CardGroup>

Do not label `validEntries` as a winner count. It counts inspected entries that
passed the configured filters. Winner rows exist only in the detail response.

## Build a Twitter giveaway audit handoff

Store one summary row per draw. Keep the public draw ID as the join key.
Store the source tweet URL. Usernames can change.

```json theme={null}
{
  "draw_id": "f4bd00a2-7b4e-4e59-8e1b-72e2c9f12345",
  "tweet_url": "https://x.com/xquik/status/1893456789012345678",
  "status": "completed",
  "total_entries": 847,
  "valid_entries": 312,
  "created_at": "2026-02-24T10:00:00.000Z",
  "drawn_at": "2026-02-24T10:05:00.000Z",
  "detail_path": "/api/v1/draws/f4bd00a2-7b4e-4e59-8e1b-72e2c9f12345",
  "winner_export_path": "/api/v1/draws/f4bd00a2-7b4e-4e59-8e1b-72e2c9f12345/export?format=csv&type=winners"
}
```

Fetch detail rows before publishing past giveaway winners. Keep winner
position and `isBackup`. Dashboards and announcements then cannot show a backup
winner as a primary winner.

## Query parameters

<ParamField query="limit" type="number">
  Results per page. Default `50`, max `100`.
</ParamField>

<ParamField query="cursor" type="string">
  Cursor for pagination. Pass the `nextCursor` value from a previous response to fetch the next page. An edited or unknown cursor returns `400`.
</ParamField>

## Headers

<ParamField header="x-api-key" type="string" required>
  Send your Xquik API key. Generate one from the [dashboard](https://xquik.com/dashboard).
</ParamField>

<ParamField header="Authorization" type="string">
  Send `Bearer <token>` instead of `x-api-key` when using OAuth 2.1.
</ParamField>

## Response

### 200 OK

<ResponseField name="draws" type="array">
  List of draw objects ordered by creation date (newest first).
  **Draw object fields.**

  <ResponseField name="id" type="string">
    Draw public ID returned by Xquik.
  </ResponseField>

  <ResponseField name="tweetUrl" type="string">
    Original tweet URL used for the draw.
  </ResponseField>

  <ResponseField name="status" type="string">
    Draw status (for example `completed`).
  </ResponseField>

  <ResponseField name="totalEntries" type="number">
    Candidate entries inspected for the draw.
  </ResponseField>

  <ResponseField name="validEntries" type="number">
    Entries that passed all filters.
  </ResponseField>

  <ResponseField name="createdAt" type="string">
    ISO 8601 creation timestamp.
  </ResponseField>

  <ResponseField name="drawnAt" type="string">
    ISO 8601 timestamp of when Xquik selected winners. Present only for completed draws.
  </ResponseField>
</ResponseField>

<ResponseField name="hasMore" type="boolean">
  `true` if more pages exist beyond this result set.
</ResponseField>

<ResponseField name="nextCursor" type="string">
  Pagination cursor. Pass it as `cursor` for the next page.
</ResponseField>

```json theme={null}
{
  "draws": [
    {
      "id": "f4bd00a2-7b4e-4e59-8e1b-72e2c9f12345",
      "tweetUrl": "https://x.com/xquik/status/1893456789012345678",
      "status": "completed",
      "totalEntries": 847,
      "validEntries": 312,
      "createdAt": "2026-02-24T10:00:00.000Z",
      "drawnAt": "2026-02-24T10:05:00.000Z"
    },
    {
      "id": "9a78ce15-2f3d-4f90-a86b-1049c7a26e92",
      "tweetUrl": "https://x.com/xquik/status/1893456789012340000",
      "status": "completed",
      "totalEntries": 1240,
      "validEntries": 980,
      "createdAt": "2026-02-23T16:30:00.000Z",
      "drawnAt": "2026-02-23T16:35:00.000Z"
    }
  ],
  "hasMore": true,
  "nextCursor": "MjAyNi0wMi0yM1QxNjozMDowMC4wMDBafDY2NjY1"
}
```

### 400 Invalid cursor

```json theme={null}
{
  "error": "invalid_input",
  "message": "Cursor invalid. Use nextCursor from the previous page, or omit it to start over."
}
```

The `cursor` value is not a `nextCursor` from this route. Send the last
`nextCursor` you received, or omit `cursor` to start from the first page.

### 401 Unauthenticated

```json theme={null}
{ "error": "unauthenticated" }
```

Missing or invalid API key / session cookie.

### 429 Rate limited

```json theme={null}
{
  "error": "rate_limit_exceeded",
  "message": "Too many requests. Try again later.",
  "retryAfter": 1
}
```

Too many requests. Wait for the `Retry-After` header before retrying.

## Paginate Twitter giveaway history

Draws use cursor pagination. Pass `nextCursor` as the next `cursor` value.

<CodeGroup>
  ```bash First page theme={null}
  curl --fail-with-body "https://xquik.com/api/v1/draws?limit=10" \
    -H "x-api-key: xq_YOUR_KEY_HERE" | jq
  ```

  ```bash Next page theme={null}
  curl --fail-with-body "https://xquik.com/api/v1/draws?limit=10&cursor=MjAyNi0wMi0yM1QxNjozMDowMC4wMDBafDY2NjY1" \
    -H "x-api-key: xq_YOUR_KEY_HERE" | jq
  ```
</CodeGroup>

Continue fetching pages until `hasMore` is `false`. Cursors are opaque strings. Do not parse or build them.

Use this loop to export the complete history:

```javascript Node.js theme={null}
const seenCursors = new Set();
const draws = [];
let cursor;

do {
  const url = new URL("https://xquik.com/api/v1/draws");
  url.searchParams.set("limit", "100");
  if (cursor) url.searchParams.set("cursor", cursor);

  const response = await fetch(url, {
    headers: { "x-api-key": "xq_YOUR_KEY_HERE" },
  });
  const page = await response.json();
  if (!response.ok) {
    throw new Error(page.message || "Giveaway history page failed.");
  }

  draws.push(...page.draws);
  const next = page.nextCursor;
  if (page.hasMore && (!next || seenCursors.has(next))) {
    throw new Error("Giveaway history cursor did not advance.");
  }

  if (next) seenCursors.add(next);
  cursor = page.hasMore ? next : undefined;
} while (cursor);

process.stdout.write(`${JSON.stringify(draws)}\n`);
```

Save the last accepted cursor after you store each batch. Restart from that
cursor after a worker failure. Never build a cursor from timestamps or draw
IDs.

## Handle giveaway history responses

<CardGroup cols={2}>
  <Card title="200 Draw page" icon="circle-check">
    Read `draws` and `hasMore`. Read `nextCursor` only when another page exists.
  </Card>

  <Card title="400 Invalid cursor" icon="circle-alert">
    The cursor is not one this route returned. Resend the last `nextCursor`.
  </Card>

  <Card title="401 Authentication" icon="key-round">
    Authentication failed. Replace the API key or OAuth bearer token first.
  </Card>

  <Card title="429 Rate limit" icon="timer">
    Too many requests. Honor `Retry-After`, then resume with the same cursor.
  </Card>
</CardGroup>

Do not advance the cursor after a failed request. A retry must request the same
page. Append results only after the response succeeds.

## Twitter giveaway history questions

### How do I view past Twitter giveaway draws?

Call `GET /draws` with your Xquik API key. The newest draw summaries appear
first. Follow `nextCursor` for older results.

### Does giveaway history include past winners?

The list response does not include winners. Pass its `id` to `GET /draws/{id}`
for primary and backup winner rows.

### Can I download previous Twitter giveaway winners?

Yes. Fetch the draw ID first. Then export `type=winners` in CSV, JSON,
Markdown, PDF, text, or XLSX.

### What do total and valid entries mean?

`totalEntries` counts inspected candidate entries. `validEntries` counts
entries that passed the draw filters. Neither field reports the winner count.

### How do I audit a Twitter giveaway result?

Store the list summary and draw ID. Fetch draw details and keep winner
order. Export entries when the review needs every inspected reply.

### Does listing giveaway draws consume credits?

No. Listing draw history is free. Running a new draw can consume credits.

<Note>
  **Related.** [Get Draw](/api-reference/draws/get) retrieves one result. Use
  [Create Draw](/api-reference/draws/create) for a new winner selection.
</Note>


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