---
title: "Request an upload of a recipe build input (a file, or a folder as an uncompressed tar), by content"
method: POST
path: "/v1/organizations/{organization_id}/template-uploads"
tags: ["Template builds"]
---

# Request an upload of a recipe build input (a file, or a folder as an uncompressed tar), by content

`POST /v1/organizations/{organization_id}/template-uploads`

## Request

- Base URL: `https://api.shardflux.dev`
- URL: `https://api.shardflux.dev/v1/organizations/{organization_id}/template-uploads`
- Auth: HTTP bearer

200 {upload, put: null} when the organization already has these bytes (a pending upload is checked in the bucket first). 201 with a presigned S3 PUT otherwise (valid 900 s): send the bytes with every header of `put.headers` (x-amz-checksum-sha256 and content-length are signed, so S3 refuses other bytes), then reference `sha256:<hex>` in the recipe’s build.files. Idempotent by content (no Idempotency-Key needed). Errors: 422 upload_too_large (details.limit upload_bytes_max: at most 5 GiB), 422 upload_digest_mismatch (the same sha256 is available with another size), 503 dependency_unavailable (uploads_not_configured). Owners/admins and API keys with a tool permission.

## Path parameters

- `organization_id` string, uuid, required

## Request body

- TemplateUploadRequest
  - `sha256` string, required: Lower-case hex SHA-256 of the bytes.
  - `size` integer, required: Bytes, at most 5368709120 (5 GiB; more is 422 upload_too_large).
  - `kind` 'file' | 'tar', required: file, or tar (an uncompressed ustar/pax archive of a folder). Recorded for display; the recipe entry decides.

## Response `200`

200: the bytes are already available (put null). 201: PUT the bytes with `put`, then reference `sha256:<hex>` in the recipe.

- TemplateUploadResponse: 200: the bytes are already available (put null). 201: PUT the bytes with `put`, then reference `sha256:<hex>` in the recipe.
  - `upload` TemplateUpload, required
    - `sha256` string, required
    - `size` integer, required
    - `kind` 'file' | 'tar', required
    - `state` 'pending' | 'available', required: available: verified in the bucket (a recipe may reference it as sha256:<hex>); pending: PUT the bytes first.
    - `created_at` string, date-time, required: RFC 3339 UTC timestamp with Z.
    - `verified_at` string, date-time, nullable, required: RFC 3339 UTC timestamp with Z.
  - `put` object, nullable, required
    - `url` string, required: Presigned S3 PutObject URL (a bearer credential until expires_at: do not log or share it).
    - `method` 'PUT', required
    - `headers` object, required: Send every header verbatim (x-amz-checksum-sha256 and content-length are signed; S3 refuses other bytes).
    - `expires_at` string, date-time, required: RFC 3339 UTC timestamp with Z.

## Other responses

- `201`: 200: the bytes are already available (put null). 201: PUT the bytes with `put`, then reference `sha256:<hex>` in the recipe.
- `4XX`: Default Response
- `5XX`: Default Response

---

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