presigned-uploads
Use when the user has files larger than ~50 MB to extract via the cloud, or when base64-encoding the body would be wasteful. Covers the three-step presign / PUT / confirm flow against POST /v1/uploads/presign and POST /v1/uploads/confirm.
- License 许可
- Apache-2.0
- 最近更新
- 2026-11-11
- Stars
- ★ 1.6k
- Forks
- 468
01 前言 Front Matter
- name
- presigned-uploads
- description
- Use when the user has files larger than ~50 MB to extract via the cloud, or when base64-encoding the body would be wasteful. Covers the three-step presign / PUT / confirm flow against POST /v1/uploads/presign and POST /v1/uploads/confirm.
03 SKILL.md 正文
Presigned uploads
For files larger than about 50 MB, skip the base64-in-JSON body of
POST /v1/extract and use the three-step presigned-upload flow instead.
The client uploads bytes directly to object storage, then tells the API to
start processing.
When to reach for this
- Single file > 50 MB.
- Batch with aggregate body size > 100 MB.
- Bandwidth-constrained environments where double-encoding (base64 + TLS
- worker) wastes throughput.
- File already lives in S3 / GCS and you can stream rather than buffer.
The three steps
1. POST /v1/uploads/presign → batch_id + per-file presigned PUT URLs
2. PUT <upload_url> → upload each file's bytes directly
3. POST /v1/uploads/confirm → start extraction, returns job_ids
Step 1 returns one upload_url per document. Step 3 cannot run until
every PUT in step 2 succeeds.
Step 1 — presign
curl -X POST https://api.kreuzberg.dev/v1/uploads/presign \
-H "Authorization: Bearer $KREUZBERG_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"documents": [
{"filename": "scan.pdf", "mime_type": "application/pdf"},
{"filename": "report.docx", "mime_type": "application/vnd.openxmlformats-officedocument.wordprocessingml.document"}
],
"config": {"output_format": "markdown"},
"webhook": {"url": "https://hooks.example.com/x"}
}'
Response
{
"batch_id": "batch_550e8400-e29b-41d4-a716",
"uploads": [
{
"job_id": "550e8400-...",
"upload_url": "https://storage.googleapis.com/kreuzberg-dev-uploads/...",
"object_key": "projects/abc123/uploads/550e8400-...",
"method": "PUT",
"expires_in_secs": 3600
},
{
"job_id": "660e9400-...",
"upload_url": "https://storage.googleapis.com/kreuzberg-dev-uploads/...",
"object_key": "projects/abc123/uploads/660e9400-...",
"method": "PUT",
"expires_in_secs": 3600
}
]
}
Keep the batch_id — you need it for step 3. URLs expire in 3600 seconds
(1 hour); upload before then.
Step 2 — PUT to each upload URL
The presigned URL is signed by Google Cloud Storage; PUT directly to it,
without an Authorization header. Set Content-Type to match the
mime_type declared in step 1:
curl -X PUT "<upload_url>" \
-H "Content-Type: application/pdf" \
--data-binary @scan.pdf
A successful upload returns 200 OK with no body. Do this for every
entry in uploads before moving on.
Step 3 — confirm
curl -X POST https://api.kreuzberg.dev/v1/uploads/confirm \
-H "Authorization: Bearer $KREUZBERG_API_KEY" \
-H "Content-Type: application/json" \
-d '{"batch_id": "batch_550e8400-e29b-41d4-a716"}'
Response (202)
{
"job_ids": ["550e8400-...", "660e9400-..."],
"status": "processing"
}
These are the same job_id values returned in step 1's uploads array.
From here, the flow is identical to offloading-extraction — poll
GET /v1/jobs/{id} or wait for the webhook.
End-to-end curl example
#!/usr/bin/env bash
set -euo pipefail
API="https://api.kreuzberg.dev"
KEY="$KREUZBERG_API_KEY"
FILE="scan.pdf"
# 1. Presign
resp=$(curl -fsS -X POST "$API/v1/uploads/presign" \
-H "Authorization: Bearer $KEY" \
-H "Content-Type: application/json" \
-d '{"documents":[{"filename":"'"$FILE"'","mime_type":"application/pdf"}]}')
batch_id=$(echo "$resp" | jq -r .batch_id)
upload_url=$(echo "$resp" | jq -r '.uploads[0].upload_url')
# 2. PUT
curl -fsS -X PUT "$upload_url" \
-H "Content-Type: application/pdf" \
--data-binary "@$FILE"
# 3. Confirm
curl -fsS -X POST "$API/v1/uploads/confirm" \
-H "Authorization: Bearer $KEY" \
-H "Content-Type: application/json" \
-d '{"batch_id":"'"$batch_id"'"}' | jq .
Errors
| Status | Where | Cause |
|---|---|---|
400 |
presign | Empty documents, bad MIME, missing filename. |
403 |
PUT | URL expired (>1h since presign) or Content-Type mismatch. |
400 |
confirm | One or more uploads missing in storage. |
401 |
presign/confirm | Bad Bearer token. |
If confirm returns 400 complaining about a missing upload, retry the
PUT for that specific object_key — confirmation requires every file to
be present in storage first.
When not to use this
For files under ~5 MB, the JSON data field is simpler and lower-latency
(one round trip instead of three). See the offloading-extraction skill.
04 同仓库更多 Skills
deja-search
deja-vu memory — search the user's past AI coding sessions with the deja CLI. Holds what they already settled and never wrote into the repo (naming rules, banned or already-tried tools, required checks before merge, preferred values, who owns what). Use before your first edit in a task, before you call a change done or ready to merge, before you recommend a tool, library, design or reviewer, before re-debugging an error that may already be solved, when they say 'didn't we fix this before', 'what did we decide about X' or 'I already have that', and before telling them something on this machine does not exist.
deja-reflect
End-of-session reflection and memory curation with deja-vu. Review what was decided, what commands broke and what repaired them, and record durable project rules or decisions with deja remember so the next session starts with them.
revid
Make, edit, export and post AI videos with Revid (revid.ai) through the Revid MCP server. Use whenever the user wants a short-form or long-form video made (from an idea, a script, a URL, an article, a PDF, a tweet, a product page, their own clips, or a song), wants to find what is going viral on TikTok, YouTube, Instagram or X before making something, wants to edit or re-export an existing Revid project, generate a standalone AI image or clip, make a series episode, or publish and schedule a finished video to connected social accounts. Covers setup (hosted MCP with OAuth, or an API key), the 36 tools, credits, polling and the rules for publishing. Routes to the more specific revid-* skills when one fits.
review-study
Review a QuestionPunk survey before launch for wording, answer choices, branching, and missing settings. Use for check my survey or review this draft before publishing.
manage-study
Find QuestionPunk studies, check status, publish an explicitly requested draft, or retrieve its participant link. Use for find my survey, publish this study, or how many people responded.
create-study
Create a saved QuestionPunk survey draft from a research brief or edit specified questions. Use for requests such as make a customer feedback survey or shorten my onboarding study.