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

# Direct Upload

> Request a pre-signed upload URL for content evaluation

## Authentication

**Required:** API Key authentication via `X-API-Key` header

## Overview

This endpoint initiates an event-driven evaluation flow:

1. API creates evaluation job record with status `awaiting_upload`
2. API generates pre-signed GCS upload URL
3. Client uploads content directly to GCS using PUT request
4. Evaluation triggered on upload completion
5. Webhook notification sent to client

## Request Body

<ParamField body="judge_id" type="string" required>
  The ID of the judge to use for evaluation
</ParamField>

<ParamField body="content_type" type="string" required>
  The type of content being uploaded

  **Allowed values:** `video`, `image`, `audio`
</ParamField>

<ParamField body="filename" type="string" required>
  The original filename of the content. Must be between 1-255 characters.
</ParamField>

<ParamField body="file_size_bytes" type="integer" required>
  The size of the file in bytes.
</ParamField>

<ParamField body="title" type="string">
  Optional title for the content
</ParamField>

<ParamField body="description" type="string">
  Optional description for the content
</ParamField>

<ParamField body="webhook_url" type="string">
  Optional webhook URL to override your organization's default webhook. Intended for easier sandbox testing

  If provided, this URL will receive notifications for this batch. The webhook will still use your organization's webhook secret for request signing.
</ParamField>

## Request Example

### cURL

```bash theme={null}
curl -X POST "https://api.getpique.ai/v1/evaluations/presigned-upload" \
  -H "X-API-Key: pk_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "judge_id": "judge_abc123",
    "content_type": "video",
    "filename": "safety_test_video.mp4",
    "file_size_bytes": 52428800,
    "title": "Product Demo Video",
    "description": "Marketing video for new product launch"
  }'
```

### JSON Body

```json theme={null}
{
  "judge_id": "judge_abc123",
  "content_type": "video",
  "filename": "safety_test_video.mp4",
  "file_size_bytes": 52428800,
  "title": "Product Demo Video",
  "description": "Marketing video for new product launch"
}
```

## Response

<ResponseField name="job_id" type="string">
  Unique identifier for the evaluation job. Use this to track the evaluation status.
</ResponseField>

<ResponseField name="upload_url" type="string">
  Pre-signed GCS upload URL. Use this URL with a PUT request to upload your content.

  **Important:** This URL expires after the time specified in `expires_at` (15 minutes from creation)
</ResponseField>

<ResponseField name="upload_headers" type="object">
  Headers that must be included when uploading to the `upload_url`

  **Typically includes:**

  * Content-Type headers
  * Any required authentication headers
</ResponseField>

<ResponseField name="expires_at" type="string">
  ISO 8601 timestamp indicating when the upload URL expires (15 minutes from creation)
</ResponseField>

## Response Example

```json theme={null}
{
  "job_id": "job_xKt9mNp2qRs3vWy7",
  "upload_url": "https://storage.googleapis.com/judge-content/org_123/pending/job_xKt9mNp2qRs3vWy7/safety_test_video.mp4?X-Goog-Algorithm=GOOG4-RSA-SHA256&...",
  "upload_headers": {
    "Content-Type": "video/mp4"
  },
  "expires_at": "2024-01-15T11:30:00Z"
}
```

## Uploading Content

After receiving the response, upload your file using the provided URL:

```bash theme={null}
curl -X PUT "<UPLOAD_URL_FROM_RESPONSE>"\
  -H "Content-Type: video/mp4" \
  -T your-video.mp4 \
```

## Webhook Notifications

If configured, your webhook will receive a POST request when content processing completes:

**Headers:**

```
X-Pique-Signature: t=1732654321,v1=5d41402abc4b2a76b9719d911017c592,alg=sha256
Content-Type: application/json
```

**Completed Evaluation:**

```json theme={null}
{
  "evaluation_id": "a1922bbb-7264-4e2e-82f6-778702b05a30",
  "job_id": "job_AbC123XyZ456789",
  "content_id": "550e8400-e29b-41d4-a716-446655440000",
  "judge_id": "a1b2c3d4-e5f6-4789-9012-3456789abcde",
  "status": "completed",
  "overall_score": 0.85,
  "timestamp": "2025-11-12T23:16:08.526491Z",
  "results": [
    {
      "criterion_id": "848b9b59-2775-4303-8912-0a6ff40b6fd6",
      "detector_name": "video_specs",
      "pass_check": true,
      "score": 1,
      "rationale": "Video specs meet requirements: 576x1024 (9:16), 30.0fps, 38.0s",
      "metrics": {
        "video_specs": {
          "width": 576,
          "height": 1024,
          "aspect_ratio": "9:16",
          "fps": 30,
          "duration_sec": 38.033991,
          "audio_sample_rate": 44100
        }
      }
    }
  ]
}
```

**Failed Evaluation:**

```json theme={null}
{
  "event": "evaluation.failed",
  "job_id": "job_3vp2mT7dJh5vhZmpk2G_yg",
  "status": "failed",
  "timestamp": "2025-11-12T23:16:08.526491Z",
  "error": "Failed to process video",
  "judge_id": "9e8ed8b4-e4ff-4137-9469-11181586a9e6"
}
```

### Webhook Endpoint Implementation Guidelines

Expected Response: Your webhook endpoint should return a 200 OK response. Any other status code will be considered a failure and may trigger retries.

Timeout: Webhook requests timeout after 10 seconds. Ensure your endpoint responds within this time.

Retries: Pique will retry failed webhook deliveries with exponential backoff. Implement idempotent processing using the `job_id`.

Signing:

* Header: X-Pique-Signature: t=\<unix timestamp seconds>,v1=\<hex hmac>,alg=sha256
* Message for signing: message = f"{timestamp}.{raw_body}" (UTF-8 bytes)
* Algorithm: HMAC(secret, message, SHA256)

## Error Responses

### 400 Bad Request

* Invalid content type (must be video, image, or audio)
* Invalid request parameters

### 401 Unauthorized

Missing or invalid API key

### 404 Not Found

Judge not found or not accessible by your organization

### 500 Internal Server Error

Failed to create upload URL due to server error
