---
title: "Start a click export"
method: POST
path: "/exports"
tags: ["Exports"]
---

# Start a click export

`POST /exports`

## Request

- Base URL: `https://api.warplink.app/v1`
- URL: `https://api.warplink.app/v1/exports`
- Auth: HTTP bearer

Starts a background job that exports click rows for the organization, or for one link. The export is a snapshot: it holds the clicks committed when the job was cut. Requires an API key with the analytics:read or links:read scope. SDK keys are refused. Poll the job with GET /exports/{id}, then download the file.

## Request body

- object
  - `since` string, date-time, required: Start of the window, inclusive.
  - `until` string, date-time, required: End of the window, exclusive. Must be after since.
  - `link_id` string, uuid: Export the clicks of one link. Omit to export the whole organization.
  - `job_id` string, uuid: A job id you generate. Repeating the request with the same id and body returns the same job.

## Response `202`

The job was created

- object
  - `job` ExportJob, required: A click export job and its manifest. The same object is returned when the job is created, while it runs, and after it completes.
    - `job_id` string, uuid
    - `snapshot_id` string, uuid: Equal to job_id.
    - `org_id` string, uuid
    - `status` 'created' | 'cut' | 'running' | 'complete' | 'failed': There is no expired status: a job is expired once expires_at has passed.
    - `error` 'too_large' | 'assumption_violated' | 'attempts_exhausted' | 'storage_unavailable' | 'abandoned' | 'null', nullable: Set when status is failed.
    - `scope` 'org' | 'own_links' | 'null', nullable: The role scope applied to the rows.
    - `filters` object, nullable: Request filters, such as linkId for a single-link export.
    - `window_requested_from` string, date-time
    - `window_requested_to` string, date-time
    - `window_from` string, date-time: The window actually exported, after the plan's data retention was applied.
    - `window_to` string, date-time
    - `retention_days` integer, nullable
    - `clipped` boolean: True when the requested window was narrowed to the plan's data retention.
    - `clipped_reason` 'retention' | 'null', nullable
    - `cut_snapshot` string, nullable: The database snapshot the export was cut at. Rows committed after it are never in this export.
    - `cut_at` string, date-time, nullable
    - `server_version_num` integer, nullable
    - `membership_max_rows` integer: The most rows one export may hold. A larger request fails as too_large.
    - `created_at` string, date-time
    - `completed_at` string, date-time, nullable
    - `expires_at` string, date-time: Downloads stop working at this time.
    - `expired_at` string, date-time, nullable: When the stored file was removed after expiry.
    - `completeness` 'unmeasured' | 'measured'
    - `complete_through` string, date-time, nullable
    - `rows_in_cut` integer, nullable
    - `rows_written` integer, nullable: Data rows in the file.
    - `deletions_observed` integer, nullable: Rows in the cut that were deleted before their page was read. rows_written plus deletions_observed equals rows_in_cut.
    - `first_id` string, nullable
    - `last_id` string, nullable
    - `order` 'id asc'
    - `columns` string[]
    - `schema_version` integer
    - `page_width` integer, nullable
    - `page_count` integer, nullable
    - `pages` object[]
      - `page` integer
      - `seq_from` integer
      - `seq_to` integer
      - `rows` integer
      - `bytes` integer
      - `sha256` string
      - `first_id` string, nullable
      - `last_id` string, nullable
      - `unknown_counts` object
    - `sha256` string, nullable: SHA-256 of the whole file. Every download of a complete job returns identical bytes with this checksum.
    - `unknown_counts` object: Per column, the number of empty cells.

## Other responses

- `400`: Invalid request, including a body that is not valid JSON
- `401`: Unauthorized
- `403`: Forbidden. A Free organization that asks for an export starting before its last 30 days gets LOOKBACK_EXCEEDED, with details.earliest_allowed, and no job is created
- `404`: Not found
- `409`: The job_id was already used for a different request (code EXPORT_JOB_ID_CONFLICT), the organization already has an export running (code EXPORT_IN_PROGRESS), or its stored exports are at their size limit (code EXPORT_QUOTA_EXCEEDED)
- `422`: No part of the requested window is within your plan's data retention (code RETENTION_WINDOW_UNAVAILABLE). No job is created.
- `503`: Exports are turned off for this deployment (code EXPORTS_UNAVAILABLE). Retry later.

---

[API](https://skmtc.dev/warplink/apis/warplink-api.md) · [All operations](https://skmtc.dev/warplink/apis/warplink-api/llms.txt) · [OpenAPI document](https://skmtc.dev/warplink/apis/warplink-api/revisions/2a90ae8c44e8?raw)
