> ## Documentation Index
> Fetch the complete documentation index at: https://docs.getversive.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Complete asset upload

> Verify an uploaded file so it can be attached to a question

Checks what arrived for an upload ticket and reports its state. The call is idempotent: repeat it while `status` is `pending`, and stop once it is `ready`. `rejected` and `expired` are final, so create a new ticket instead of calling again. On the first successful check the file is verified by content (a PNG declared as JPEG is rejected), PDFs are sanitized, and the verified type and size are recorded. Only a `ready` ticket can be used as `asset.upload_id` on a question.

**upload\_id** `string` *required*

The ticket id from [Create asset upload](https://docs.getversive.com/api-reference/asset-uploads/create-asset-upload.md).

### Response

**status** `string`

`pending` while no file has been uploaded; `ready` once verified; `rejected` when the bytes failed verification (the file is deleted, create a new ticket); `expired` when completion is requested after the two-hour window; a file uploaded in time but completed late is not registered either, so create a new ticket.

**asset\_type** `string | null`

`image`, `video`, or `pdf` once ready.

**asset\_url** `string | null`

The asset's stable identifier once ready, the same `url`[List questions](https://docs.getversive.com/api-reference/questions/list-questions.md) returns for existing assets.

**download\_url** `string`

A one-hour signed link to preview the verified file. Present only when ready. It grants access to the file on its own, so do not log or share it; use `asset_url` as the identifier.

**download\_url\_expires\_at** `string`

When `download_url` stops working.

**mime\_type** `string | null`

The verified media type once ready.

**size\_bytes** `integer | null`

The verified size once ready.

**error** `string | null`

Why the upload was rejected or expired.

`asset_url` is the stable, unsigned identifier of the file; `download_url` is the only link that can fetch it. Only the caller that created the ticket can complete it: the same user for an MCP ticket, the same API key for an organization key's ticket. Anyone else, another organization, or an unknown id gets `404`.

```bash cURL theme={null}
curl -X POST "https://api.getversive.com/api/v1/asset-uploads/5c8e2f1a-7d4b-4e9c-a1f3-6b2d8c4e0a9f/complete" \
  -H "Authorization: Bearer $VERSIVE_API_KEY"
```

```json Ready theme={null}
{
  "upload_id": "5c8e2f1a-7d4b-4e9c-a1f3-6b2d8c4e0a9f",
  "status": "ready",
  "file_name": "concept-a.png",
  "mime_type": "image/png",
  "size_bytes": 184320,
  "asset_type": "image",
  "asset_url": "https://xyz.supabase.co/storage/v1/object/public/interview_media/questions/2f6c….png",
  "error": null,
  "expires_at": "2026-09-23T14:05:00.118Z",
  "created_at": "2026-09-23T12:05:00.118Z",
  "completed_at": "2026-09-23T12:06:41.002Z",
  "max_bytes": 52428800,
  "allowed_mime_types": ["application/pdf", "image/bmp", "image/gif", "image/jpeg", "image/png", "image/webp", "image/x-ms-bmp", "video/mp4", "video/quicktime", "video/webm"],
  "download_url": "https://xyz.supabase.co/storage/v1/object/sign/interview_media/questions/2f6c….png?token=…",
  "download_url_expires_at": "2026-09-23T13:06:41.002Z"
}
```

```json Rejected theme={null}
{
  "upload_id": "5c8e2f1a-7d4b-4e9c-a1f3-6b2d8c4e0a9f",
  "status": "rejected",
  "error": "File content is not a supported format",
  "asset_type": null,
  "asset_url": null
}
```


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