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

# Uploading material

> How raw footage gets to us.

**Material** is your raw input: a recording, a screen capture, a clip. It
is yours; templates never alter it, they derive from it. A run's `material`
field takes one of the following.

## A public https URL (simplest)

Pass a public `https://` URL as `material` and we fetch it server-side (with
SSRF guards). No upload step needed:

```json theme={null}
{ "material": "https://your-cdn.com/clip.mp4" }
```

## An upload ticket (for local files)

Uploading is **two calls**: mint a one-time ticket, then post the file to
it. The file call needs no API key, because the ticket is its own
single-use credential.

```bash theme={null}
# 1. Mint a ticket
curl -X POST https://api.askeditor.com/v1/uploads \
  -H "Authorization: Bearer $ASKEDITOR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "purpose": "clip for background removal" }'
# → data: { "ticket": "upl_…", "uploadUrl": "…", "expiresInSec": 1800 }

# 2. Post the file to the ticket (no auth header)
curl -X POST https://api.askeditor.com/v1/uploads/upl_…/file \
  -F "file=@clip.mp4"
# → data: { "material": "mat_…", "bytes": …, "status": "uploaded" }
```

Pass the returned **`material`** handle (`mat_…`) as the run's `material`.
(The `uploadUrl` in the ticket response is a browser path for humans to drop
a file in; from a shell, ignore it and use the `/file` endpoint above.)

Poll a ticket any time with `GET /v1/uploads/{ticket}`; its `status` goes
`pending → uploaded`, and `material` is set once the file lands.

## Via MCP

The [connector](/docs/mcp/connect)'s upload tools drive the same ticket flow for
files on the agent's machine, including large-file handling.

## What templates check

Each template declares what material it accepts (kind, duration bounds,
orientation, content requirements like "one person, front-facing"). The
check runs **before** the pipeline and before any charge: a mismatch comes
back as a [typed refusal](/docs/setting-up/refusals), not a failed render.
